IBNOS
process.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <process/process.h>
29 #include <process/handle.h>
30 #include <process/thread.h>
31 #include <process/object.h>
32 #include <hardware/gdt.h>
33 #include <memory/paging.h>
34 #include <memory/allocator.h>
35 #include <util/list.h>
36 #include <util/util.h>
37 
43 struct linkedList processList = LL_INIT(processList);
44 
45 static void __processDestroy(struct object *obj);
46 static void __processShutdown(struct object *obj, uint32_t mode);
47 static int32_t __processGetStatus(struct object *obj, UNUSED uint32_t mode);
48 static struct linkedList *__processWait(struct object *obj, UNUSED uint32_t mode, uint32_t *result);
49 
50 static const struct objectFunctions processFunctions =
51 {
52  __processDestroy,
53  NULL, /* getMinHandle */
54  __processShutdown,
55  __processGetStatus,
56  __processWait,
57  NULL, /* signal */
58  NULL, /* write */
59  NULL, /* read */
60  NULL, /* insert */
61  NULL, /* remove */
62 };
63 
77 struct process *processCreate(struct process *original)
78 {
79  struct process *p;
80 
81  /* allocate some new memory */
82  if (!(p = heapAlloc(sizeof(*p))))
83  return NULL;
84 
85  /* initialize general object info */
86  __objectInit(&p->obj, &processFunctions);
87  ll_init(&p->waiters);
88  ll_add_tail(&processList, &p->entry_list);
89  p->exitcode = -1;
90  ll_init(&p->threads);
91  p->pageDirectory = NULL;
92  p->entryPoint = NULL;
93 
94  /* initialize paging for the new process */
95  if (!original)
96  {
99 
100  pagingMapRemoteMemory(p, NULL, (void *)USERMODE_KERNELSTACK_ADDRESS, kernelStack, 1, true, false); /* kernelstack */
101  pagingMapRemoteMemory(p, NULL, (void *)USERMODE_GDT_ADDRESS, (void *)USERMODE_GDT_ADDRESS, GDT_MAX_PAGES, false, false); /* gdt */
102  pagingMapRemoteMemory(p, NULL, (void *)USERMODE_IDT_ADDRESS, (void *)USERMODE_IDT_ADDRESS, 1, false, false); /* idt */
103  pagingMapRemoteMemory(p, NULL, (void *)USERMODE_INTJMP_ADDRESS, intJmpTable_user, 1, false, false); /* intjmp */
104  pagingMapRemoteMemory(p, NULL, (void *)USERMODE_TASK_ADDRESS, (void *)USERMODE_TASK_ADDRESS, 1, false, false); /* task */
105  }
106  else
107  {
108  handleForkTable(&p->handles, &original->handles);
109  pagingForkProcessPageTable(p, original);
110  }
111 
112  p->user_programArgumentsBase = NULL;
116 
117  return p;
118 }
119 
127 static void __processDestroy(struct object *obj)
128 {
129  struct process *p = objectContainer(obj, struct process, &processFunctions);
130 
131  /* there should be no more threads waiting on this process */
132  assert(ll_empty(&p->waiters));
133 
134  /* list of threads should be empty at this point */
135  assert(ll_empty(&p->threads));
136 
137  /* free paging table (if not done yet) */
138  if (p->pageDirectory)
139  {
141  p->pageDirectory = NULL;
142  }
143 
144  /* free opened handles */
145  if (p->handles.handles)
146  {
148  p->handles.handles = NULL;
149  }
150 
151  /* unlink from list of existing processes */
152  ll_remove(&p->entry_list);
153 
154  /* release process structure memory */
155  p->obj.functions = NULL;
156  heapFree(p);
157 }
158 
167 static void __processShutdown(struct object *obj, uint32_t exitcode)
168 {
169  struct process *p = objectContainer(obj, struct process, &processFunctions);
170  struct thread *t, *__t;
171 
172  p->exitcode = exitcode;
173 
174  /* required to allow shutting down processes using borrowed references */
175  objectAddRef(p);
176 
177  /* wake up waiting threads */
178  queueWakeup(&p->waiters, true, p->exitcode);
179 
180  /* shutdown all other threads */
181  LL_FOR_EACH_SAFE(t, __t, &p->threads, struct thread, entry_process)
182  {
183  objectShutdown(t, p->exitcode);
184  }
185 
186  /* free paging table */
187  if (p->pageDirectory)
188  {
190  p->pageDirectory = NULL;
191  }
192 
193  /* free opened handles */
194  if (p->handles.handles)
195  {
197  p->handles.handles = NULL;
198  }
199 
200  objectRelease(p);
201 }
202 
215 static int32_t __processGetStatus(struct object *obj, UNUSED uint32_t mode)
216 {
217  struct process *p = objectContainer(obj, struct process, &processFunctions);
218  return ll_empty(&p->threads) ? (signed)p->exitcode : (-1);
219 }
220 
232 static struct linkedList *__processWait(struct object *obj, UNUSED uint32_t mode, uint32_t *result)
233 {
234  struct process *p = objectContainer(obj, struct process, &processFunctions);
235  if (!ll_empty(&p->threads)) return &p->waiters;
236 
237  *result = p->exitcode;
238  return NULL;
239 }
240 
245 uint32_t processCount()
246 {
247  struct process *p;
248  uint32_t count = 0;
249  LL_FOR_EACH(p, &processList, struct process, entry_list)
250  {
251  /* just increase counter */
252  count++;
253  }
254  return count;
255 }
256 
265 uint32_t processInfo(struct processInfo *info, uint32_t count)
266 {
267  uint32_t processCount = 0;
268  struct process *p;
269  struct thread *t;
270 
271  /* kernel itself */
272  if (count)
273  {
274  /* let the paging module fill out all memory related fields */
275  pagingFillProcessInfo(NULL, info);
276 
277  /* fill out all other fields */
278  info->processID = 0;
279  info->handleCount = 0;
280  info->numberOfTotalThreads = 0;
281  info->numberOfBlockedThreads = 0;
282 
283  count--;
284  info++;
285  }
286 
287  LL_FOR_EACH(p, &processList, struct process, entry_list)
288  {
289  if (count)
290  {
291  /* let the paging module fill out all memory related fields */
292  pagingFillProcessInfo(p, info);
293 
294  /* fill out all other fields */
295  info->processID = (uint32_t)p; /* FIXME: associate some other identifiers? */
296  info->handleCount = p->handles.handles ? handleCount(&p->handles) : 0;
297  info->numberOfTotalThreads = 0;
298  info->numberOfBlockedThreads = 0;
299 
300  LL_FOR_EACH(t, &p->threads, struct thread, entry_process)
301  {
302  info->numberOfTotalThreads++;
303  if (t->blocked) info->numberOfBlockedThreads++;
304  }
305 
306  count--;
307  info++;
308  }
309 
310  processCount++;
311  }
312 
313  return processCount;
314 }
315 
void * entryPoint
Definition: process.h:79
void pagingReleaseProcessPageTable(struct process *p)
Releases the page directory and page table of a specific process.
Definition: paging.c:1344
#define USERMODE_IDT_ADDRESS
Definition: gdt.h:95
struct process * processCreate(struct process *original)
Creates a new kernel process object.
Definition: process.c:77
const struct objectFunctions * functions
Definition: object.h:72
void * heapAlloc(uint32_t length)
Allocates a block of kernel memory.
Definition: allocator.c:363
void pagingAllocProcessPageTable(struct process *p)
Allocates the page directory and page table for a specific process.
Definition: paging.c:1236
#define assert(ex)
Definition: util.h:61
#define UNUSED
Definition: util.h:39
void * user_programArgumentsBase
Definition: process.h:82
#define objectShutdown(p, a)
Definition: object.h:111
#define USERMODE_GDT_ADDRESS
Definition: gdt.h:94
void handleTableInit(struct handleTable *table)
Initializes the handle table structure which is part of each process.
Definition: handle.c:48
uint32_t processCount()
Returns the number of total processes in the system.
Definition: process.c:245
void handleForkTable(struct handleTable *destination, struct handleTable *source)
Forks a handle table.
Definition: handle.c:68
void heapFree(void *addr)
Deallocates a block of kernel memory.
Definition: allocator.c:385
uint32_t numberOfTotalThreads
Definition: process.h:44
struct pagingEntry * pageDirectory
Definition: process.h:75
uint32_t handleCount(struct handleTable *table)
Returns the number of handles in a handletable.
Definition: handle.c:268
uint32_t processInfo(struct processInfo *info, uint32_t count)
Fills out the processInfo structure with information about each individual process.
Definition: process.c:265
#define LL_INIT(list)
Initializes a linkedList.
Definition: list.h:124
void * intJmpTable_user
Definition: gdt.c:54
uint32_t user_environmentVariablesLength
Definition: process.h:87
Definition: thread.h:47
struct object obj
Definition: process.h:64
void handleTableFree(struct handleTable *table)
Releases the memory of the handle table and all associated objects.
Definition: handle.c:94
#define USERMODE_KERNELSTACK_ADDRESS
Definition: gdt.h:93
struct linkedList entry_list
Definition: process.h:68
uint32_t numberOfBlockedThreads
Definition: process.h:45
struct object ** handles
Definition: handle.h:50
void * kernelStack
Definition: gdt.c:42
void * user_environmentVariablesBase
Definition: process.h:86
struct linkedList threads
Definition: process.h:72
#define objectAddRef(p)
Definition: object.h:89
#define objectContainer(p, type, functions)
Definition: object.h:66
uint32_t user_programArgumentsLength
Definition: process.h:83
uint32_t exitcode
Definition: thread.h:56
#define ll_add_tail
Definition: list.h:100
struct linkedList entry_process
Definition: thread.h:55
struct linkedList waiters
Definition: process.h:65
uint32_t processID
Definition: process.h:35
struct handleTable handles
Definition: process.h:90
#define objectRelease(p)
Definition: object.h:97
struct linkedList processList
Definition: process.c:43
#define GDT_MAX_PAGES
Definition: gdt.h:74
#define LL_FOR_EACH_SAFE(element, next_element, list, type, field)
Allows to iterate a linkedList similar to a for-loop (safe when deleting elements).
Definition: list.h:148
uint32_t handleCount
Definition: process.h:43
void pagingForkProcessPageTable(struct process *destination, struct process *source)
Duplicate a page table and assigns it to a destination process.
Definition: paging.c:1261
void pagingFillProcessInfo(struct process *p, struct processInfo *info)
Fills out all memory related fields in the processInfo structure.
Definition: paging.c:1436
char mode[8]
Definition: filesystem.h:65
#define USERMODE_TASK_ADDRESS
Definition: gdt.h:97
#define LL_FOR_EACH(element, list, type, field)
Allows to iterate a linkedList similar to a for-loop.
Definition: list.h:138
void * pagingMapRemoteMemory(struct process *dst_p, struct process *src_p, void *dst_addr, void *src_addr, uint32_t length, bool rw, bool user)
Maps some virtual memory from one process to another one.
Definition: paging.c:1150
#define USERMODE_INTJMP_ADDRESS
Definition: gdt.h:96
bool blocked
Definition: thread.h:51
uint32_t exitcode
Definition: process.h:69