Merge pull request #3365 from ntherning/fix-gc-graystack-stress-on-win64
[mono.git] / mono / io-layer / wapi.c
1
2 #include "wapi.h"
3
4 #include "event-private.h"
5 #include "io-trace.h"
6 #include "io.h"
7 #include "mutex-private.h"
8 #include "process-private.h"
9 #include "semaphore-private.h"
10 #include "shared.h"
11 #include "socket-private.h"
12
13 #include "mono/utils/mono-lazy-init.h"
14 #include "mono/utils/w32handle.h"
15
16 gboolean _wapi_has_shut_down = FALSE;
17
18 void
19 wapi_init (void)
20 {
21         _wapi_shm_semaphores_init ();
22         _wapi_io_init ();
23         _wapi_processes_init ();
24         _wapi_semaphore_init ();
25         _wapi_mutex_init ();
26         _wapi_event_init ();
27         _wapi_socket_init ();
28 }
29
30 void
31 wapi_cleanup (void)
32 {
33         g_assert (_wapi_has_shut_down == FALSE);
34         _wapi_has_shut_down = TRUE;
35
36         _wapi_error_cleanup ();
37         wapi_processes_cleanup ();
38         _wapi_io_cleanup ();
39 }
40
41 /* Use this instead of getpid(), to cope with linuxthreads.  It's a
42  * function rather than a variable lookup because we need to get at
43  * this before share_init() might have been called. */
44 static mono_lazy_init_t _wapi_pid_init_lazy = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
45 static pid_t _wapi_pid;
46
47 static void
48 _wapi_pid_init (void)
49 {
50         _wapi_pid = getpid ();
51 }
52
53 pid_t
54 wapi_getpid (void)
55 {
56         mono_lazy_initialize (&_wapi_pid_init_lazy, _wapi_pid_init);
57         return _wapi_pid;
58 }
59
60 static gboolean
61 _WAPI_SHARED_NAMESPACE (MonoW32HandleType type)
62 {
63         switch (type) {
64         case MONO_W32HANDLE_NAMEDMUTEX:
65         case MONO_W32HANDLE_NAMEDSEM:
66         case MONO_W32HANDLE_NAMEDEVENT:
67                 return TRUE;
68         default:
69                 return FALSE;
70         }
71 }
72
73 typedef struct {
74         gpointer ret;
75         MonoW32HandleType type;
76         gchar *utf8_name;
77 } _WapiSearchHandleNamespaceData;
78
79 static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
80 {
81         _WapiSearchHandleNamespaceData *search_data;
82         MonoW32HandleType type;
83         WapiSharedNamespace *sharedns;
84
85         type = mono_w32handle_get_type (handle);
86         if (!_WAPI_SHARED_NAMESPACE (type))
87                 return FALSE;
88
89         search_data = (_WapiSearchHandleNamespaceData*) user_data;
90
91         switch (type) {
92         case MONO_W32HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break;
93         case MONO_W32HANDLE_NAMEDSEM:   sharedns = &((struct _WapiHandle_namedsem*)   data)->sharedns; break;
94         case MONO_W32HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break;
95         default:
96                 g_assert_not_reached ();
97         }
98
99         if (strcmp (sharedns->name, search_data->utf8_name) == 0) {
100                 if (type != search_data->type) {
101                         /* Its the wrong type, so fail now */
102                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
103                                 __func__, handle, mono_w32handle_ops_typename (type));
104                         search_data->ret = INVALID_HANDLE_VALUE;
105                 } else {
106                         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
107                                 __func__, handle);
108                         search_data->ret = handle;
109                 }
110
111                 return TRUE;
112         }
113
114         return FALSE;
115 }
116
117 /* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for
118  * not found
119  */
120 gpointer _wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name)
121 {
122         _WapiSearchHandleNamespaceData search_data;
123
124         g_assert(_WAPI_SHARED_NAMESPACE(type));
125
126         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
127                 __func__, utf8_name, mono_w32handle_ops_typename (type));
128
129         search_data.ret = NULL;
130         search_data.type = type;
131         search_data.utf8_name = utf8_name;
132         mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data);
133         return search_data.ret;
134 }
135
136 /* Lots more to implement here, but this is all we need at the moment */
137 gboolean
138 DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
139         guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
140 {
141         if (srcprocess != _WAPI_PROCESS_CURRENT || targetprocess != _WAPI_PROCESS_CURRENT) {
142                 /* Duplicating other process's handles is not supported */
143                 SetLastError (ERROR_INVALID_HANDLE);
144                 return FALSE;
145         }
146
147         if (src == _WAPI_PROCESS_CURRENT) {
148                 *target = _wapi_process_duplicate ();
149         } else {
150                 mono_w32handle_ref (src);
151                 *target = src;
152         }
153
154         return TRUE;
155 }
156
157 /**
158  * CloseHandle:
159  * @handle: The handle to release
160  *
161  * Closes and invalidates @handle, releasing any resources it
162  * consumes.  When the last handle to a temporary or non-persistent
163  * object is closed, that object can be deleted.  Closing the same
164  * handle twice is an error.
165  *
166  * Return value: %TRUE on success, %FALSE otherwise.
167  */
168 gboolean CloseHandle(gpointer handle)
169 {
170         if (handle == INVALID_HANDLE_VALUE){
171                 SetLastError (ERROR_INVALID_PARAMETER);
172                 return FALSE;
173         }
174         if (handle == (gpointer)0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
175                 /* Problem: because we map file descriptors to the
176                  * same-numbered handle we can't tell the difference
177                  * between a bogus handle and the handle to stdin.
178                  * Assume that it's the console handle if that handle
179                  * exists...
180                  */
181                 SetLastError (ERROR_INVALID_PARAMETER);
182                 return FALSE;
183         }
184
185         mono_w32handle_unref (handle);
186         return TRUE;
187 }