UMS Worker

A UMS worker thread is a regular pthread that has entered the UMS working mode.

Enter UMS working mode

A UMS worker thread is created by calling the ums_pthread_create() function.

The function is implemented as follows:

src/lib/src/worker.c
53int ums_pthread_create(pthread_t *thread, ums_attr_t *ums_attr,
54			     void *(*func)(void *), void *args)
55{
56	worker_proc_args_t *ums_args;
57
58	if (!ums_attr || !func) {
59		errno = EFAULT;
60		return -1;
61	}
62
63	ums_args = malloc(sizeof(*ums_args));
64	if (!ums_args)
65		return -1;
66
67	ums_args->completion_list = ums_attr->completion_list;
68	ums_args->func = func;
69	ums_args->args = args;
70
71	return pthread_create(thread,
72			      ums_attr->pthread_attr,
73			      worker_wrapper_routine,
74			      ums_args);
75}

where worker_proc_args_t is defined as

src/lib/src/worker.c
5typedef struct worker_proc_args_s {
6	ums_completion_list_t completion_list;
7	void *(*func)(void *);
8	void *args;
9} worker_proc_args_t;

The worker_wrapper_routine is the routine executed by the newly created pthread: it starts entering the UMS worker mode and then executing the user specified function.

In particular:

src/lib/src/worker.c
11static pthread_key_t worker_key;
12static pthread_once_t worker_key_once = PTHREAD_ONCE_INIT;
13
14static inline int exit_ums_mode(void)
15{
16	return ioctl(UMS_FILENO, IOCTL_EXIT_UMS);
17}
18
19static void destroy_worker_key(void *args)
20{
21	free(args);
22	(void) exit_ums_mode();
23}
24
25static void create_worker_key(void)
26{
27	(void) pthread_key_create(&worker_key, destroy_worker_key);
28}
29
30static void *worker_wrapper_routine(void *args)
31{
32	worker_proc_args_t *worker_args = args;
33
34	struct enter_ums_mode_args ums_args = {
35		.flags = ENTER_UMS_WORK,
36		.ums_complist = worker_args->completion_list
37	};
38
39	(void) pthread_once(&worker_key_once, create_worker_key);
40
41	// enter ums mode and deschedule worker thread (suspend here)
42	if (enter_ums_mode(&ums_args)) {
43		free(args);
44		return NULL;
45	}
46
47	(void) pthread_setspecific(worker_key, args);
48
49	// worker thread is now active for scheduling
50	return worker_args->func(worker_args->args);
51}

The worker_key contains the unique worker_wrapper_routine argument specific for each worker thread. When the user specified function calls pthread_exit(), returns or is cancelled because of a pthread_cancel() request, the destructor routine destroy_worker_key is called releasing every resource associated with that UMS worker thread.

UMS worker yield

The yielding of a UMS worker thread is implemented as follows:

src/lib/src/worker.c
77int ums_thread_yield(void *scheduler_param)
78{
79	return ioctl(UMS_FILENO, IOCTL_UMS_YIELD, scheduler_param);
80}