1 /**
2  * \file
3  */
4 
5 #ifndef _MONO_METADATA_W32HANDLE_H_
6 #define _MONO_METADATA_W32HANDLE_H_
7 
8 #include <config.h>
9 #include <glib.h>
10 
11 #ifdef HOST_WIN32
12 #include <windows.h>
13 #endif
14 
15 #include "mono/utils/mono-coop-mutex.h"
16 
17 #ifndef INVALID_HANDLE_VALUE
18 #define INVALID_HANDLE_VALUE (gpointer)-1
19 #endif
20 
21 #define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64
22 
23 #ifndef MONO_INFINITE_WAIT
24 #define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF)
25 #endif
26 
27 typedef enum {
28 	MONO_W32TYPE_UNUSED = 0,
29 	MONO_W32TYPE_SEM,
30 	MONO_W32TYPE_MUTEX,
31 	MONO_W32TYPE_EVENT,
32 	MONO_W32TYPE_PROCESS,
33 	MONO_W32TYPE_NAMEDMUTEX,
34 	MONO_W32TYPE_NAMEDSEM,
35 	MONO_W32TYPE_NAMEDEVENT,
36 	MONO_W32TYPE_COUNT
37 } MonoW32Type;
38 
39 typedef struct {
40 	MonoW32Type type;
41 	guint ref;
42 	gboolean signalled;
43 	gboolean in_use;
44 	MonoCoopMutex signal_mutex;
45 	MonoCoopCond signal_cond;
46 	gpointer specific;
47 } MonoW32Handle;
48 
49 typedef enum {
50 	MONO_W32HANDLE_WAIT_RET_SUCCESS_0   =  0,
51 	MONO_W32HANDLE_WAIT_RET_ABANDONED_0 =  MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS,
52 	MONO_W32HANDLE_WAIT_RET_ALERTED     = -1,
53 	MONO_W32HANDLE_WAIT_RET_TIMEOUT     = -2,
54 	MONO_W32HANDLE_WAIT_RET_FAILED      = -3,
55 } MonoW32HandleWaitRet;
56 
57 typedef struct
58 {
59 	void (*close)(gpointer handle, gpointer data);
60 
61 	/* mono_w32handle_signal_and_wait */
62 	void (*signal)(MonoW32Handle *handle_data);
63 
64 	/* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple,
65 	 * with the handle locked (shared handles aren't locked.)
66 	 * Returns TRUE if ownership was established, false otherwise.
67 	 * If TRUE, *abandoned contains a status code such as
68 	 * WAIT_OBJECT_0 or WAIT_ABANDONED_0.
69 	 */
70 	gboolean (*own_handle)(MonoW32Handle *handle_data, gboolean *abandoned);
71 
72 	/* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple, if the
73 	 * handle in question is "ownable" (ie mutexes), to see if the current
74 	 * thread already owns this handle
75 	 */
76 	gboolean (*is_owned)(MonoW32Handle *handle_data);
77 
78 	/* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple,
79 	 * if the handle in question needs a special wait function
80 	 * instead of using the normal handle signal mechanism.
81 	 * Returns the mono_w32handle_wait_one return code.
82 	 */
83 	MonoW32HandleWaitRet (*special_wait)(MonoW32Handle *handle_data, guint32 timeout, gboolean *alerted);
84 
85 	/* Called by mono_w32handle_wait_one and mono_w32handle_wait_multiple,
86 	 * if the handle in question needs some preprocessing before the
87 	 * signal wait.
88 	 */
89 	void (*prewait)(MonoW32Handle *handle_data);
90 
91 	/* Called when dumping the handles */
92 	void (*details)(MonoW32Handle *handle_data);
93 
94 	/* Called to get the name of the handle type */
95 	const gchar* (*typename) (void);
96 
97 	/* Called to get the size of the handle type */
98 	gsize (*typesize) (void);
99 } MonoW32HandleOps;
100 
101 typedef enum {
102 	MONO_W32HANDLE_CAP_WAIT         = 0x01,
103 	MONO_W32HANDLE_CAP_SIGNAL       = 0x02,
104 	MONO_W32HANDLE_CAP_OWN          = 0x04,
105 	MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
106 } MonoW32HandleCapability;
107 
108 void
109 mono_w32handle_init (void);
110 
111 void
112 mono_w32handle_cleanup (void);
113 
114 void
115 mono_w32handle_register_ops (MonoW32Type type, MonoW32HandleOps *ops);
116 
117 gpointer
118 mono_w32handle_new (MonoW32Type type, gpointer handle_specific);
119 
120 gpointer
121 mono_w32handle_duplicate (MonoW32Handle *handle_data);
122 
123 gboolean
124 mono_w32handle_close (gpointer handle);
125 
126 const gchar*
127 mono_w32handle_get_typename (MonoW32Type type);
128 
129 gboolean
130 mono_w32handle_lookup_and_ref (gpointer handle, MonoW32Handle **handle_data);
131 
132 void
133 mono_w32handle_unref (MonoW32Handle *handle_data);
134 
135 void
136 mono_w32handle_foreach (gboolean (*on_each)(MonoW32Handle *handle_data, gpointer user_data), gpointer user_data);
137 
138 void
139 mono_w32handle_dump (void);
140 
141 void
142 mono_w32handle_register_capabilities (MonoW32Type type, MonoW32HandleCapability caps);
143 
144 void
145 mono_w32handle_set_signal_state (MonoW32Handle *handle_data, gboolean state, gboolean broadcast);
146 
147 gboolean
148 mono_w32handle_issignalled (MonoW32Handle *handle_data);
149 
150 void
151 mono_w32handle_lock (MonoW32Handle *handle_data);
152 
153 gboolean
154 mono_w32handle_trylock (MonoW32Handle *handle_data);
155 
156 void
157 mono_w32handle_unlock (MonoW32Handle *handle_data);
158 
159 MonoW32HandleWaitRet
160 mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable);
161 
162 MonoW32HandleWaitRet
163 mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waitall, guint32 timeout, gboolean alertable);
164 
165 MonoW32HandleWaitRet
166 mono_w32handle_signal_and_wait (gpointer signal_handle, gpointer wait_handle, guint32 timeout, gboolean alertable);
167 
168 #ifdef HOST_WIN32
169 static inline MonoW32HandleWaitRet
mono_w32handle_convert_wait_ret(guint32 res,guint32 numobjects)170 mono_w32handle_convert_wait_ret (guint32 res, guint32 numobjects)
171 {
172 	if (res >= WAIT_OBJECT_0 && res <= WAIT_OBJECT_0 + numobjects - 1)
173 		return MONO_W32HANDLE_WAIT_RET_SUCCESS_0 + (res - WAIT_OBJECT_0);
174 	else if (res >= WAIT_ABANDONED_0 && res <= WAIT_ABANDONED_0 + numobjects - 1)
175 		return MONO_W32HANDLE_WAIT_RET_ABANDONED_0 + (res - WAIT_ABANDONED_0);
176 	else if (res == WAIT_IO_COMPLETION)
177 		return MONO_W32HANDLE_WAIT_RET_ALERTED;
178 	else if (res == WAIT_TIMEOUT)
179 		return MONO_W32HANDLE_WAIT_RET_TIMEOUT;
180 	else if (res == WAIT_FAILED)
181 		return MONO_W32HANDLE_WAIT_RET_FAILED;
182 	else
183 		g_error ("%s: unknown res value %d", __func__, res);
184 }
185 #endif
186 
187 
188 #endif /* _MONO_METADATA_W32HANDLE_H_ */
189