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