-
-
Save plvhx/f0d9ec906fb1a6e60c846082971b34ea to your computer and use it in GitHub Desktop.
lock hierarchy with sequentailly running thread routine.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <pthread.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #ifndef NORETURN | |
| #define NORETURN(x) ((void)(x)) | |
| #endif | |
| #ifndef UNUSED | |
| #define UNUSED NORETURN | |
| #endif | |
| struct llist { | |
| int data; | |
| pthread_mutex_t lock; | |
| struct llist *next; | |
| struct llist *prev; | |
| }; | |
| #define LLIST_INIT_NULL(list) \ | |
| struct llist *(list) = NULL | |
| static struct llist *llist_init(int data) | |
| { | |
| int ret; | |
| struct llist *llist; | |
| llist = calloc(1, sizeof(struct llist)); | |
| if (!llist) | |
| return NULL; | |
| ret = pthread_mutex_init(&llist->lock, NULL); | |
| if (ret != 0) | |
| goto __release; | |
| ret = pthread_mutex_lock(&llist->lock); | |
| if (ret != 0) | |
| goto __destroy_lock; | |
| llist->data = data; | |
| ret = pthread_mutex_unlock(&llist->lock); | |
| if (ret != 0) | |
| goto __destroy_lock; | |
| llist->next = NULL; | |
| llist->prev = NULL; | |
| return llist; | |
| __destroy_lock: | |
| NORETURN(pthread_mutex_destroy(&llist->lock)); | |
| __release: | |
| free(llist); | |
| __fallback: | |
| return NULL; | |
| } | |
| static void llist_insert(struct llist **llist, int data) | |
| { | |
| struct llist *tmp, *tlist; | |
| if (!*llist) { | |
| *llist = llist_init(data); | |
| return; | |
| } | |
| tmp = *llist; | |
| while (tmp->next != NULL) | |
| tmp = tmp->next; | |
| tlist = llist_init(data); | |
| if (!tlist) | |
| return; | |
| tmp->next = tlist; | |
| tlist->prev = tmp; | |
| return; | |
| } | |
| static int __llist_get_data(struct llist *llist) | |
| { | |
| int ret; | |
| NORETURN(pthread_mutex_lock(&llist->lock)); | |
| ret = llist->data; | |
| NORETURN(pthread_mutex_unlock(&llist->lock)); | |
| return ret; | |
| } | |
| #define __llist_for_each(ptr, llist) \ | |
| for ((ptr) = (llist); (ptr) != NULL; (ptr) = (ptr)->next) | |
| static void *thread_insertion_routine(void *arg) | |
| { | |
| int i; | |
| struct llist **inflist = (struct llist **)arg; | |
| for (i = 0; i < 10; i++) | |
| llist_insert(inflist, i); | |
| return NULL; | |
| } | |
| static void *thread_printer_routine(void *arg) | |
| { | |
| struct llist *lptr; | |
| struct llist **inflist = (struct llist **)arg; | |
| __llist_for_each(lptr, *inflist) | |
| printf("%d\n", __llist_get_data(lptr)); | |
| return NULL; | |
| } | |
| static void __llist_destroy(struct llist *llist) | |
| { | |
| if (llist == NULL) | |
| return; | |
| __llist_destroy(llist->next); | |
| NORETURN(pthread_mutex_destroy(&llist->lock)); | |
| free(llist); | |
| return; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| UNUSED(argc); | |
| UNUSED(argv); | |
| LLIST_INIT_NULL(llist); | |
| int ret; | |
| pthread_t tir_id, tpr_id; | |
| ret = pthread_create( | |
| &tir_id, | |
| NULL, | |
| thread_insertion_routine, | |
| &llist | |
| ); | |
| if (ret != 0) | |
| return -1; | |
| ret = pthread_join(tir_id, NULL); | |
| if (ret != 0) | |
| return -1; | |
| ret = pthread_create( | |
| &tpr_id, | |
| NULL, | |
| thread_printer_routine, | |
| &llist | |
| ); | |
| if (ret != 0) | |
| return -1; | |
| ret = pthread_join(tpr_id, NULL); | |
| if (ret != 0) | |
| return -1; | |
| __llist_destroy(llist); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment