Usermode/libc - Fix strchr and strrchr behavior
[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         LOG("Added deferred %p{um=%p,cb=%p,handler=%p}",
48                 Call, Call->Unmarshal, Call->cb, Call->Handler);
49         Workqueue_AddWork(&gUDI_DeferredWorkQueue, Call);
50 }
51
52 tUDI_DeferredCall *UDI_int_AllocDeferred(udi_cb_t *cb, udi_op_t *handler, tUDI_DeferredUnmarshal *Unmarshal, size_t extra)
53 {
54         tUDI_DeferredCall *ret = NEW( tUDI_DeferredCall, + extra );
55         ret->Unmarshal = Unmarshal;
56         ret->Handler = handler;
57         ret->cb = cb;
58         return ret;
59
60
61
62 typedef void    udi_op_cb_t(udi_cb_t *gcb);
63 void UDI_int_MakeDeferredCb(udi_cb_t *cb, udi_op_t *handler)
64 {
65         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCb, 0);
66         UDI_int_AddDeferred(call);
67 }
68 void UDI_int_Deferred_UnmashalCb(tUDI_DeferredCall *Call)
69 {
70         UDI_int_ChannelReleaseFromCall(Call->cb);
71         ((udi_op_cb_t*)Call->Handler)(Call->cb);
72         free(Call);
73 }
74
75 typedef void    udi_op_cbu8_t(udi_cb_t *gcb, udi_ubit8_t arg1);
76 struct sData_CbU8 {
77         udi_ubit8_t     arg1;
78 };
79 void UDI_int_MakeDeferredCbU8(udi_cb_t *cb, udi_op_t *handler, udi_ubit8_t arg1)
80 {
81         struct sData_CbU8       *data;
82         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbU8, sizeof(*data));
83         data = (void*)(call + 1);
84         data->arg1 = arg1;
85         UDI_int_AddDeferred(call);
86 }
87 void UDI_int_Deferred_UnmashalCbU8(tUDI_DeferredCall *Call)
88 {
89         struct sData_CbU8 *data = (void*)(Call+1);
90         UDI_int_ChannelReleaseFromCall(Call->cb);
91         ((udi_op_cbu8_t*)Call->Handler)(Call->cb, data->arg1);
92         free(Call);
93 }
94
95 typedef void    udi_op_cbs_t(udi_cb_t *gcb, udi_status_t status);
96 struct sData_CbS {
97         udi_status_t    status;
98 };
99 void UDI_int_MakeDeferredCbS(udi_cb_t *cb, udi_op_t *handler, udi_status_t status)
100 {
101         struct sData_CbS        *data;
102         tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbS, sizeof(*data));
103         data = (void*)(call + 1);
104         data->status = status;
105         UDI_int_AddDeferred(call);
106 }
107 void UDI_int_Deferred_UnmashalCbS(tUDI_DeferredCall *Call)
108 {
109         struct sData_CbS *data = (void*)(Call+1);
110         UDI_int_ChannelReleaseFromCall(Call->cb);
111         ((udi_op_cbs_t*)Call->Handler)(Call->cb, data->status);
112         free(Call);
113 }
114

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