Whamcloud - gitweb
Landing b_hd_newconfig on HEAD
[fs/lustre-release.git] / lnet / libcfs / winnt / winnt-curproc.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=4:tabstop=4:
3  *
4  *  Copyright (c) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or modify it under
9  *   the terms of version 2 of the GNU General Public License as published by
10  *   the Free Software Foundation. Lustre is distributed in the hope that it
11  *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
12  *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details. You should have received a
14  *   copy of the GNU General Public License along with Lustre; if not, write
15  *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
16  *   USA.
17  *
18  * Impletion of winnt curproc routines.
19  */
20
21 #define DEBUG_SUBSYSTEM S_LNET
22
23 #include <libcfs/libcfs.h>
24 #include <libcfs/kp30.h>
25
26
27 /*
28  * Implementation of cfs_curproc API (see portals/include/libcfs/curproc.h)
29  * for Linux kernel.
30  */
31
32 cfs_task_t this_task = 
33     { 0, 0, 0, 0, 0, 0, 0, 
34       0, 0, 0, 0,  1, 0,  0, 0, 0,
35       "sysetm\0" };
36
37
38 uid_t  cfs_curproc_uid(void)
39 {
40     return this_task.uid;
41 }
42
43 gid_t  cfs_curproc_gid(void)
44 {
45     return this_task.gid;
46 }
47
48 uid_t  cfs_curproc_fsuid(void)
49 {
50     return this_task.fsuid;
51 }
52
53 gid_t cfs_curproc_fsgid(void)
54 {
55     return this_task.fsgid;
56 }
57
58 pid_t cfs_curproc_pid(void)
59 {
60     return cfs_current()->pid;
61 }
62
63 int cfs_curproc_groups_nr(void)
64 {
65     return this_task.ngroups;
66 }
67
68 void cfs_curproc_groups_dump(gid_t *array, int size)
69 {
70     LASSERT(size <= NGROUPS);
71     size = min_t(int, size, this_task.ngroups);
72     memcpy(array, this_task.groups, size * sizeof(__u32));
73 }
74
75 int cfs_curproc_is_in_groups(gid_t gid)
76 {
77     return in_group_p(gid);
78 }
79
80 mode_t cfs_curproc_umask(void)
81 {
82     return this_task.umask;
83 }
84
85 char  *cfs_curproc_comm(void)
86 {
87     return this_task.comm;
88 }
89
90 cfs_kernel_cap_t cfs_curproc_cap_get(void)
91 {
92     return this_task.cap_effective;
93 }
94
95 void cfs_curproc_cap_set(cfs_kernel_cap_t cap)
96 {
97     this_task.cap_effective = cap;
98 }
99
100
101 /*
102  * Implementation of linux task management routines
103  */
104
105
106 /* global of the task manager structure */
107
108 TASK_MAN TaskMan;
109
110
111 /*
112  *  task slot routiens
113  */
114
115 PTASK_SLOT
116 alloc_task_slot()
117 {
118     PTASK_SLOT task = NULL;
119
120     if (TaskMan.slab) {
121         task = cfs_mem_cache_alloc(TaskMan.slab, 0);
122     } else {
123         task = cfs_alloc(sizeof(TASK_SLOT), 0);
124     }
125
126     return task;
127 }
128
129 void
130 init_task_slot(PTASK_SLOT task)
131 {
132     memset(task, 0, sizeof(TASK_SLOT));
133     task->Magic = TASKSLT_MAGIC;
134     task->task  = this_task;
135     task->task.pid = (pid_t)PsGetCurrentThreadId();
136     cfs_init_event(&task->Event, TRUE, FALSE);
137 }
138
139
140 void
141 cleanup_task_slot(PTASK_SLOT task)
142 {
143     if (TaskMan.slab) {
144         cfs_mem_cache_free(TaskMan.slab, task);
145     } else {
146         cfs_free(task);
147     }
148 }
149
150 /*
151  *  task manager related routines
152  */
153
154 VOID
155 task_manager_notify(
156     IN HANDLE   ProcessId,
157     IN HANDLE   ThreadId,
158     IN BOOLEAN  Create
159     )
160 {
161     PLIST_ENTRY ListEntry = NULL; 
162     PTASK_SLOT  TaskSlot  = NULL;
163
164     spin_lock(&(TaskMan.Lock));
165
166     ListEntry = TaskMan.TaskList.Flink;
167
168     while (ListEntry != (&(TaskMan.TaskList))) {
169
170         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
171
172         if (TaskSlot->Pid == ProcessId && TaskSlot->Tid == ThreadId) {
173
174             if (Create) {
175 /*
176                 DbgPrint("task_manager_notify: Pid=%xh Tid %xh resued (TaskSlot->Tet = %xh)...\n",
177                          ProcessId, ThreadId, TaskSlot->Tet);
178 */
179             } else {
180                 /* remove the taskslot */
181                 RemoveEntryList(&(TaskSlot->Link));
182                 TaskMan.NumOfTasks--;
183
184                 /* now free the task slot */
185                 cleanup_task_slot(TaskSlot);
186             }
187         }
188
189         ListEntry = ListEntry->Flink;
190     }
191
192     spin_unlock(&(TaskMan.Lock));
193 }
194
195 int
196 init_task_manager()
197 {
198     NTSTATUS    status;
199
200     /* initialize the content and magic */
201     memset(&TaskMan, 0, sizeof(TASK_MAN));
202     TaskMan.Magic = TASKMAN_MAGIC;
203
204     /* initialize the spinlock protection */
205     spin_lock_init(&TaskMan.Lock);
206
207     /* create slab memory cache */
208     TaskMan.slab = cfs_mem_cache_create(
209         "TSLT", sizeof(TASK_SLOT), 0, 0);
210
211     /* intialize the list header */
212     InitializeListHead(&(TaskMan.TaskList));
213
214     /* set the thread creation/destruction notify routine */
215     status = PsSetCreateThreadNotifyRoutine(task_manager_notify);
216
217     if (!NT_SUCCESS(status)) {
218         cfs_enter_debugger();
219     }
220
221     return 0;
222 }
223
224 void
225 cleanup_task_manager()
226 {
227     PLIST_ENTRY ListEntry = NULL; 
228     PTASK_SLOT  TaskSlot  = NULL;
229
230     /* we must stay in system since we succeed to register the
231        CreateThreadNotifyRoutine: task_manager_notify */
232     cfs_enter_debugger();
233
234
235     /* cleanup all the taskslots attached to the list */
236     spin_lock(&(TaskMan.Lock));
237
238     while (!IsListEmpty(&(TaskMan.TaskList))) {
239
240         ListEntry = TaskMan.TaskList.Flink;
241         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
242
243         RemoveEntryList(ListEntry);
244         cleanup_task_slot(TaskSlot);
245     }
246
247     spin_unlock(&TaskMan.Lock);
248
249     /* destroy the taskslot cache slab */
250     cfs_mem_cache_destroy(TaskMan.slab);
251     memset(&TaskMan, 0, sizeof(TASK_MAN));
252 }
253
254
255 /*
256  * schedule routines (task slot list)
257  */
258
259
260 cfs_task_t *
261 cfs_current()
262 {
263     HANDLE      Pid = PsGetCurrentProcessId();
264     HANDLE      Tid = PsGetCurrentThreadId();
265     PETHREAD    Tet = PsGetCurrentThread();
266
267     PLIST_ENTRY ListEntry = NULL; 
268     PTASK_SLOT  TaskSlot  = NULL;
269
270     spin_lock(&(TaskMan.Lock));
271
272     ListEntry = TaskMan.TaskList.Flink;
273
274     while (ListEntry != (&(TaskMan.TaskList))) {
275
276         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
277
278         if (TaskSlot->Pid == Pid && TaskSlot->Tid == Tid) {
279             if (TaskSlot->Tet != Tet) {
280
281 /*
282                 DbgPrint("cfs_current: Pid=%xh Tid %xh Tet = %xh resued (TaskSlot->Tet = %xh)...\n",
283                          Pid, Tid, Tet, TaskSlot->Tet);
284 */
285                 //
286                 // The old thread was already exit. This must be a
287                 // new thread which get the same Tid to the previous.
288                 //
289
290                 TaskSlot->Tet = Tet;
291             }
292             break;
293
294         } else {
295
296             if ((ULONG)TaskSlot->Pid > (ULONG)Pid) {
297                 TaskSlot = NULL;
298                 break;
299             } else if ((ULONG)TaskSlot->Pid == (ULONG)Pid) {
300                 if ((ULONG)TaskSlot->Tid > (ULONG)Tid) {
301                     TaskSlot = NULL;
302                     break;
303                 }
304             }
305
306             TaskSlot =  NULL;
307         }
308
309         ListEntry = ListEntry->Flink;
310     }
311
312     if (!TaskSlot) {
313
314         TaskSlot = alloc_task_slot();
315
316         if (!TaskSlot) {
317             cfs_enter_debugger();
318             goto errorout;
319         }
320
321         init_task_slot(TaskSlot);
322
323         TaskSlot->Pid = Pid;
324         TaskSlot->Tid = Tid;
325         TaskSlot->Tet = Tet;
326
327         if (ListEntry == (&(TaskMan.TaskList))) {
328             //
329             // Empty case or the biggest case, put it to the tail.
330             //
331             InsertTailList(&(TaskMan.TaskList), &(TaskSlot->Link));
332         } else {
333             //
334             // Get a slot and smaller than it's tid, put it just before.
335             //
336             InsertHeadList(ListEntry->Blink, &(TaskSlot->Link));
337         }
338
339         TaskMan.NumOfTasks++;
340     }
341
342     //
343     // To Check whether he task structures are arranged in the expected order ?
344     //
345
346     {
347         PTASK_SLOT  Prev = NULL, Curr = NULL;
348         
349         ListEntry = TaskMan.TaskList.Flink;
350
351         while (ListEntry != (&(TaskMan.TaskList))) {
352
353             Curr = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
354             ListEntry = ListEntry->Flink;
355
356             if (Prev) {
357                 if ((ULONG)Prev->Pid > (ULONG)Curr->Pid) {
358                     cfs_enter_debugger();
359                 } else if ((ULONG)Prev->Pid == (ULONG)Curr->Pid) {
360                     if ((ULONG)Prev->Tid > (ULONG)Curr->Tid) {
361                         cfs_enter_debugger();
362                     }
363                 }
364             }
365
366             Prev = Curr;
367         }
368     }
369
370 errorout:
371
372     spin_unlock(&(TaskMan.Lock));
373
374     if (!TaskSlot) {
375         cfs_enter_debugger();
376         return NULL;
377     }
378
379     return (&(TaskSlot->task));
380 }
381
382 int
383 schedule_timeout(int64_t time)
384 {
385     cfs_task_t * task = cfs_current();
386     PTASK_SLOT   slot = NULL;
387
388     if (!task) {
389         cfs_enter_debugger();
390         return 0;
391     }
392
393     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
394     cfs_assert(slot->Magic == TASKSLT_MAGIC);
395
396     if (time == MAX_SCHEDULE_TIMEOUT) {
397         time = 0;
398     }
399
400     return (cfs_wait_event(&(slot->Event), time) != 0);
401 }
402
403 int
404 schedule()
405 {
406     return schedule_timeout(0);
407 }
408
409 int
410 wake_up_process(
411     cfs_task_t * task
412     )
413 {
414     PTASK_SLOT   slot = NULL;
415
416     if (!task) {
417         cfs_enter_debugger();
418         return 0;
419     }
420
421     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
422     cfs_assert(slot->Magic == TASKSLT_MAGIC);
423
424     cfs_wake_event(&(slot->Event));
425
426     return TRUE;
427 }
428
429 void
430 sleep_on(
431     cfs_waitq_t *waitq
432     )
433 {
434         cfs_waitlink_t link;
435         
436         cfs_waitlink_init(&link);
437         cfs_waitq_add(waitq, &link);
438         cfs_waitq_wait(&link, CFS_TASK_INTERRUPTIBLE);
439         cfs_waitq_del(waitq, &link);
440 }
441
442 EXPORT_SYMBOL(cfs_curproc_uid);
443 EXPORT_SYMBOL(cfs_curproc_pid);
444 EXPORT_SYMBOL(cfs_curproc_gid);
445 EXPORT_SYMBOL(cfs_curproc_fsuid);
446 EXPORT_SYMBOL(cfs_curproc_fsgid);
447 EXPORT_SYMBOL(cfs_curproc_umask);
448 EXPORT_SYMBOL(cfs_curproc_comm);
449 EXPORT_SYMBOL(cfs_curproc_groups_nr);
450 EXPORT_SYMBOL(cfs_curproc_groups_dump);
451 EXPORT_SYMBOL(cfs_curproc_is_in_groups);
452 EXPORT_SYMBOL(cfs_curproc_cap_get);
453 EXPORT_SYMBOL(cfs_curproc_cap_set);