cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / ioutil.c
bloba0091bffd5f0de9f3e3a1028672a47629ce21089
1 /*
2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
4 */
5 #include "cmogstored.h"
7 static pthread_mutex_t cleanup_lock = PTHREAD_MUTEX_INITIALIZER;
9 static pthread_mutex_t iou_lock = PTHREAD_MUTEX_INITIALIZER;
10 static Hash_table *dev_iou; /* maps system device IDs to utilization */
11 struct ioutil;
12 struct ioutil {
13 dev_t st_dev;
14 bool in_use;
15 struct ioutil *free_next;
16 char util[MOG_IOUTIL_LEN];
19 static size_t iou_hash(const void *entry, size_t tablesize)
21 const struct ioutil *iou = entry;
23 return iou->st_dev % tablesize;
26 static bool iou_cmp(const void *_a, const void *_b)
28 const struct ioutil *a = _a;
29 const struct ioutil *b = _b;
31 return a->st_dev == b->st_dev;
34 __attribute__((destructor)) static void iou_destructor(void)
36 hash_free(dev_iou);
39 __attribute__((constructor)) static void iou_constructor(void)
41 dev_iou = hash_initialize(7, NULL, iou_hash, iou_cmp, free);
42 mog_oom_if_null(dev_iou);
45 static bool cleanup_begin_i(void *ent, void *unused)
47 struct ioutil *iou = ent;
48 iou->in_use = false;
49 return true;
52 void mog_iou_cleanup_begin(void)
54 CHECK(int, 0, pthread_mutex_lock(&cleanup_lock));
55 CHECK(int, 0, pthread_mutex_lock(&iou_lock));
56 hash_do_for_each(dev_iou, cleanup_begin_i, NULL);
57 CHECK(int, 0, pthread_mutex_unlock(&iou_lock));
60 static bool freelist_append(void *ent, void *f)
62 struct ioutil *iou = ent;
63 struct ioutil **free_head = f;
65 if (iou->in_use)
66 return true;
68 assert(iou->free_next == NULL && "free_next set");
70 /* prepend current item to the free list */
71 iou->free_next = *free_head;
72 *free_head = iou;
74 return true;
77 void mog_iou_cleanup_finish(void)
79 struct ioutil *fl = NULL;
81 CHECK(int, 0, pthread_mutex_lock(&iou_lock));
83 /* build up the free list */
84 hash_do_for_each(dev_iou, freelist_append, &fl);
86 /* release items in the free list */
87 while (fl) {
88 struct ioutil *next = fl->free_next;
89 struct ioutil *found = hash_delete(dev_iou, fl);
90 assert(found == fl && "freelist found does not match");
91 free(fl);
92 fl = next;
95 CHECK(int, 0, pthread_mutex_unlock(&iou_lock));
96 CHECK(int, 0, pthread_mutex_unlock(&cleanup_lock));
99 static struct ioutil * iou_vivify(dev_t st_dev)
101 struct ioutil lookup = { .st_dev = st_dev };
102 struct ioutil *iou = hash_lookup(dev_iou, &lookup);
104 if (!iou) {
105 iou = xmalloc(sizeof(*iou));
106 iou->st_dev = st_dev;
107 iou->util[0] = '-';
108 iou->util[1] = 0;
109 iou->free_next = NULL;
110 CHECK(int, 1, hash_insert_if_absent(dev_iou, iou, NULL));
112 iou->in_use = true;
114 return iou;
117 void mog_iou_read(dev_t st_dev, char buf[MOG_IOUTIL_LEN])
119 struct ioutil *iou;
121 CHECK(int, 0, pthread_mutex_lock(&iou_lock));
122 iou = iou_vivify(st_dev);
123 memcpy(buf, iou->util, MOG_IOUTIL_LEN);
124 CHECK(int, 0, pthread_mutex_unlock(&iou_lock));
127 void mog_iou_write(dev_t st_dev, const char buf[MOG_IOUTIL_LEN])
129 struct ioutil *iou;
131 CHECK(int, 0, pthread_mutex_lock(&iou_lock));
132 iou = iou_vivify(st_dev);
133 memcpy(iou->util, buf, MOG_IOUTIL_LEN);
134 CHECK(int, 0, pthread_mutex_unlock(&iou_lock));
137 /* marks the given device as in-use */
138 void mog_iou_active(dev_t st_dev)
140 CHECK(int, 0, pthread_mutex_lock(&iou_lock));
141 (void)iou_vivify(st_dev);
142 CHECK(int, 0, pthread_mutex_unlock(&iou_lock));