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