UMS library lifecycle

All UMS objects are private to each process that opens the UMS device. Indeed every process that opens the UMS device gets allocated a private pool of UMS schedulers, UMS workers and completion lists.

Every time that the library is loaded the UMS device is opened and a per-process file descriptor, named UMS_FILENO, is initialized. All subsequentes ioctl calls for interacting with the kernel module are performed upon that file descriptor. Every time that the library is unloaded the UMS device is closed, releasing all kernel resources that are associated with the process.

That initialization and deinitialization is implemented through constructor and destructor functions annotated respectively with __attribute__((constructor)) and __attribute__((destructor)) attributes.

In particular the UMS_FILENO is declared as

src/lib/src/private.h
20extern int UMS_FILENO;

and it is managed at

src/lib/src/hooks.c
15/**
16 * @brief Open UMS file descriptor
17 */
18static void ums_fileno_open(void)
19{
20	UMS_FILENO = open("/dev/" UMS_DEV_NAME, O_RDONLY);
21}
22
23/**
24 * @brief Close UMS file descriptor
25 */
26static void ums_fileno_close(void)
27{
28	close(UMS_FILENO);
29}
30
31/**
32 * @brief Handler executed in the child process after fork processing completes
33 */
34static void ums_atfork_child_handler(void)
35{
36	ums_fileno_close();
37	ums_fileno_open();
38}
39
40/**
41 * @brief UMS library ctor
42 * 
43 * This function initializes UMS library.
44 */
45__attribute__((constructor))
46static void ums_init(void)
47{
48	ums_fileno_open();
49	(void) pthread_atfork(NULL, NULL, ums_atfork_child_handler);
50}
51
52/**
53 * @brief UMS library dtor
54 * 
55 * This function deinitializes UMS library.
56 */
57__attribute__((destructor))
58static void ums_exit(void)
59{
60	ums_fileno_close();
61}

Due to file descriptors inheritance between parent and child processes, the pthread_atfork() function registers an handler that is executed in the child process after fork() processing completes; that handler is in charge of closing the UMS_FILENO and reopening it, resulting thus in two separate pools of UMS resources for the two processes.