Skip to content

Instantly share code, notes, and snippets.

@plvhx
Created October 31, 2025 08:38
Show Gist options
  • Select an option

  • Save plvhx/f0d9ec906fb1a6e60c846082971b34ea to your computer and use it in GitHub Desktop.

Select an option

Save plvhx/f0d9ec906fb1a6e60c846082971b34ea to your computer and use it in GitHub Desktop.
lock hierarchy with sequentailly running thread routine.
#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