/ duct-tape / src / semaphore.c
semaphore.c
 1  #include <darlingserver/duct-tape/semaphore.h>
 2  #include <darlingserver/duct-tape/task.h>
 3  
 4  #include <mach/semaphore.h>
 5  #include <mach/task.h>
 6  
 7  #include <stdlib.h>
 8  
 9  dtape_semaphore_t* dtape_semaphore_create(dtape_task_t* owning_task, int initial_value) {
10  	dtape_semaphore_t* semaphore = malloc(sizeof(dtape_semaphore_t));
11  	if (!semaphore) {
12  		return NULL;
13  	}
14  
15  	semaphore->owning_task = owning_task;
16  
17  	if (semaphore_create(&semaphore->owning_task->xnu_task, &semaphore->xnu_semaphore, 0, initial_value) != KERN_SUCCESS) {
18  		free(semaphore);
19  		return NULL;
20  	}
21  
22  	return semaphore;
23  };
24  
25  void dtape_semaphore_destroy(dtape_semaphore_t* semaphore) {
26  	if (semaphore_destroy(&semaphore->owning_task->xnu_task, semaphore->xnu_semaphore) != KERN_SUCCESS) {
27  		panic("Failed to destroy duct-taped XNU semaphore");
28  	}
29  
30  	free(semaphore);
31  };
32  
33  void dtape_semaphore_up(dtape_semaphore_t* semaphore) {
34  	if (semaphore_signal(semaphore->xnu_semaphore) != KERN_SUCCESS) {
35  		panic("Failed to raise up-count of duct-taped XNU semaphore");
36  	}
37  };
38  
39  dtape_semaphore_wait_result_t dtape_semaphore_down(dtape_semaphore_t* semaphore) {
40  	kern_return_t kr = semaphore_wait(semaphore->xnu_semaphore);
41  	switch (kr) {
42  		case KERN_SUCCESS:
43  			return dtape_semaphore_wait_result_ok;
44  		case KERN_ABORTED:
45  			return dtape_semaphore_wait_result_interrupted;
46  		default:
47  			return dtape_semaphore_wait_result_error;
48  	}
49  };
50  
51  bool dtape_semaphore_down_simple(dtape_semaphore_t* semaphore) {
52  	switch (dtape_semaphore_down(semaphore)) {
53  		case dtape_semaphore_wait_result_ok:
54  			return true;
55  		case dtape_semaphore_wait_result_interrupted:
56  			return false;
57  		default:
58  			panic("Failed to lower up-count of duct-taped XNU semaphore");
59  	}
60  };