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>
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 */
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)
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
;
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
;
68 assert(iou
->free_next
== NULL
&& "free_next set");
70 /* prepend current item to the free list */
71 iou
->free_next
= *free_head
;
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 */
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");
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
);
105 iou
= xmalloc(sizeof(*iou
));
106 iou
->st_dev
= st_dev
;
109 iou
->free_next
= NULL
;
110 CHECK(int, 1, hash_insert_if_absent(dev_iou
, iou
, NULL
));
117 void mog_iou_read(dev_t st_dev
, char buf
[MOG_IOUTIL_LEN
])
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
])
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
));