Modules/UDI - Implementing proper enumeration framework
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / deferred_calls.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * deferred_calls.c
6  * - UDI Deferred call code
7  *
8  * Used to prevent excessive recursion causing stack exhaustion
9  */
10 #define DEBUG   0
11 #include <acess.h>
12 #include <udi.h>
13 #include "udi_internal.h"
14 #include <workqueue.h>
15
16 // === PROTOTYPES ===
17 void UDI_int_Deferred_UnmashalCb(tUDI_DeferredCall *Call);
18 void UDI_int_Deferred_UnmashalCbU8(tUDI_DeferredCall *Call);
19 void UDI_int_Deferred_UnmashalCbS(tUDI_DeferredCall *Call);
20
21 // === GLOBALS ===
22 tWorkqueue      gUDI_DeferredWorkQueue;
23
24 // === CODE ===
25 void UDI_int_DeferredThread(void *unused)
26 {
27         Threads_SetName("UDI Deferred");
28         Workqueue_Init(&gUDI_DeferredWorkQueue, "UDI Deferred", offsetof(tUDI_DeferredCall, Next));
29         
30         for(;;)
31         {
32                 tUDI_DeferredCall *call = Workqueue_GetWork(&gUDI_DeferredWorkQueue);
33                 
34                 if( !call )
35                 {
36                         Log_Notice("UDI", "Deferred thread worken with no work");
37                         continue ;
38                 }
39                 
40                 // Ummarshal calls handler and frees the call
41                 call->Unmarshal( call );
42         }
43 }
44
45 void UDI_int_AddDeferred(tUDI_DeferredCall *Call)
46 {
47         Workqueue_AddWork(&gUDI_DeferredWorkQueue, Call);
48 }
49
50 tUDI_DeferredCall *UDI_int_AllocDeferred(udi_cb_t *cb, udi_op_t *handler, tUDI_DeferredUnmarshal *Unmarshal, size_t extra)
51 {
52         tUDI_DeferredCall *ret = NEW( tUDI_DeferredCall, + extra );
53         ret->Unmarshal = Unmarshal;
54         ret->Handler = handler;
55         ret->cb = cb;
56         return ret;
57
58
59
60 typedef void    udi_op_cb_t(udi_cb_t *gcb);
61 void UDI_int_MakeDeferredCb(udi_cb_t *cb, udi_op_t *handler)
62 {
63         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCb, 0);
64         UDI_int_AddDeferred(call);
65 }
66 void UDI_int_Deferred_UnmashalCb(tUDI_DeferredCall *Call)
67 {
68         UDI_int_ChannelReleaseFromCall(Call->cb);
69         ((udi_op_cb_t*)Call->Handler)(Call->cb);
70         free(Call);
71 }
72
73 typedef void    udi_op_cbu8_t(udi_cb_t *gcb, udi_ubit8_t arg1);
74 struct sData_CbU8 {
75         udi_ubit8_t     arg1;
76 };
77 void UDI_int_MakeDeferredCbU8(udi_cb_t *cb, udi_op_t *handler, udi_ubit8_t arg1)
78 {
79         struct sData_CbU8       *data;
80         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbU8, sizeof(*data));
81         data = (void*)(call + 1);
82         data->arg1 = arg1;
83         UDI_int_AddDeferred(call);
84 }
85 void UDI_int_Deferred_UnmashalCbU8(tUDI_DeferredCall *Call)
86 {
87         struct sData_CbU8 *data = (void*)(Call+1);
88         UDI_int_ChannelReleaseFromCall(Call->cb);
89         ((udi_op_cbu8_t*)Call->Handler)(Call->cb, data->arg1);
90         free(Call);
91 }
92
93 typedef void    udi_op_cbs_t(udi_cb_t *gcb, udi_status_t status);
94 struct sData_CbS {
95         udi_status_t    status;
96 };
97 void UDI_int_MakeDeferredCbS(udi_cb_t *cb, udi_op_t *handler, udi_status_t status)
98 {
99         struct sData_CbS        *data;
100         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbS, sizeof(*data));
101         data = (void*)(call + 1);
102         data->status = status;
103         UDI_int_AddDeferred(call);
104 }
105 void UDI_int_Deferred_UnmashalCbS(tUDI_DeferredCall *Call)
106 {
107         struct sData_CbS *data = (void*)(Call+1);
108         UDI_int_ChannelReleaseFromCall(Call->cb);
109         ((udi_op_cbs_t*)Call->Handler)(Call->cb, data->status);
110         free(Call);
111 }
112

UCC git Repository :: git.ucc.asn.au