Skip to content

Commit

Permalink
Decouple thread startup from thread creation (#72)
Browse files Browse the repository at this point in the history
* Have the `CREATE_THREAD` system call bind the thread it creates to a
descriptor.
* Decouple starting a thread (`START_THREAD`) from creating a thread
(`CREATE_THREAD`). This way, a process can be given the permissions
needed to manage a thread pool but not to create threads itself, to
allow a system service to control resource usage.
* Add `JOIN_THREAD` system call.
  • Loading branch information
phaubertin authored Oct 25, 2024
1 parent 38c57db commit ce60c73
Show file tree
Hide file tree
Showing 54 changed files with 954 additions and 261 deletions.
2 changes: 1 addition & 1 deletion COPYING
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2019-2022 Philippe Aubertin.
Copyright (C) 2019-2024 Philippe Aubertin.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
6 changes: 6 additions & 0 deletions devel/qemu/check-log.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ echo "* Check errno was set to JINUE_EPERM"
RESULT=`grep -F -A 1 "Attempting to call jinue_receive() on the send-only descriptor." $1`
echo "$RESULT" | grep -F 'operation not permitted' || fail

echo "* Check client thread started and got the right argument"
grep -F "Client thread is starting with argument: 0xb01dface" $1 || fail

echo "* Check main thread received message from client thread"
grep -F "Main thread received message" $1 || fail

Expand Down Expand Up @@ -110,6 +113,9 @@ echo "$RESULT" | grep -F 'I/O error' || fail
echo "* Check client thread exited cleanly"
grep -F "Client thread is exiting." $1 || fail

echo "* Check main thread joined the client thread and retrieved its exit value"
grep -F "Client thread exit value is 0xdeadbeef." $1 || fail

echo "* Check the main thread initiated the reboot"
grep -F "Main thread is running." $1 || fail
grep -F "Rebooting." $1 || fail
Expand Down
6 changes: 4 additions & 2 deletions doc/syscalls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@
| 9 | [CREATE_ENDPOINT](create-endpoint.md) | Create IPC Endpoint |
| 10 | [RECEIVE](receive.md) | Receive Message |
| 11 | [REPLY](reply.md) | Reply to Message |
| 12 | [EXIT_THREAD](exit-thread.md) | Exit the Current Thread |
| 12 | [EXIT_THREAD](exit-thread.md) | Terminate the Current Thread |
| 13 | [MMAP](mmap.md) | Map Memory |
| 14 | [CREATE_PROCESS](create-process.md) | Create Process |
| 15 | [MCLONE](mclone.md) | Clone a Memory Mapping |
| 16 | [DUP](dup.md) | Duplicate a Descriptor |
| 17 | [CLOSE](close.md) | Close a Descriptor |
| 18 | [DESTROY](destroy.md) | Destroy a Kernel Object |
| 19 | [MINT](mint.md) | Mint a Descriptor |
| 20-4095 | - | Reserved |
| 20 | [START_THREAD](start-thread.md) | Start a Thread |
| 21 | [JOIN_THREAD](join-thread.md) | Wait for a Thread to Exit |
| 22-4095 | - | Reserved |
| 4096+ | [SEND](send.md) | Send Message |

#### Reserved Function Numbers
Expand Down
4 changes: 2 additions & 2 deletions doc/syscalls/create-endpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ The descriptor number to bind to the new IPC endpoint is set in `arg1`.

## Return Value

On success, this function returns the descriptor number for the new IPC endpoint
(in `arg0`). On failure, it returns -1 and an error number is set (in `arg1`).
On success, this function returns 0 (in `arg0`). On failure, this function
returns -1 and an error number is set (in `arg1`).

## Errors

Expand Down
33 changes: 16 additions & 17 deletions doc/syscalls/create-thread.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

## Description

Create a new thread in a target process.
Create a new thread in a target process and bind it to a thread descriptor.

For this operation to succeed, the descriptor for the target process
must have the
[JINUE_PERM_CREATE_THREAD](../../include/jinue/shared/asm/permissions.h) and
[JINUE_PERM_OPEN](../../include/jinue/shared/asm/permissions.h) permissions.

## Arguments

Function number (`arg0`) is 4.

The descriptor number for the target process is set in `arg1`.
The descriptor number to bind to the new thread is set in `arg1`.

The address where code execution will start is set in `arg2` and the
value of the initial stack pointer is set in `arg3`.
The descriptor number for the target process is set in `arg2`.

```
+----------------------------------------------------------------+
Expand All @@ -20,17 +24,17 @@ value of the initial stack pointer is set in `arg3`.
31 0
+----------------------------------------------------------------+
| process | arg1
| thread descriptor number | arg1
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| code entry point address | arg2
| process descriptor number | arg2
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| user stack address | arg3
| reserved (0) | arg3
+----------------------------------------------------------------+
31 0
```
Expand All @@ -42,13 +46,8 @@ returns -1 and an error number is set (in `arg1`).

## Errors

* JINUE_EINVAL if the code entry point is set to a kernel address.
* JINUE_EINVAL if the user stack address is set to a kernel address.
* JINUE_EAGAIN if the thread could not be created because of needed resources.
* JINUE_EBADF if the specified descriptor is invalid, or does not refer to a
process, or is closed.

## Future Direction

This system call will be modified to bind the new thread to a descriptor so
other system calls can refer to it e.g. to destroy it, join it, etc.
* JINUE_EBADF if the specified descriptor is already in use.
* JINUE_EBADF if the target process descriptor is invalid, or does not refer to
a process, or is closed.
* JINUE_EPERM if the specified process descriptor does not have the permissions
to create a thread and bind a descriptor into the process.
17 changes: 13 additions & 4 deletions doc/syscalls/dup.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@

Create a copy of a descriptor from the current process in a target process.

A owner descriptor cannot be duplicated with this (or any) function. A owner
descriptor is the descriptor that was specified in the call to the function
that created a kernel resource (e.g. [CREATE_ENDPOINT](create-endpoint.md)) and that
can be used to [mint](mint.md) other descriptors to that resource.
For this operation to succeed, the descriptor for the target process
must have the [JINUE_PERM_OPEN](../../include/jinue/shared/asm/permissions.h)
permission.

A owner descriptor cannot be duplicated with this (or any) function. The owner
descriptor for a given kernel resource is the original descriptor to which the
resource was bound when it was created through the relevant system call (e.g.
[CREATE_ENDPOINT](create-endpoint) for an IPC endpoint). While a owner
descriptor cannot be duplicated using this function, the [MINT](mint.md)
function can be used instead to create a new descriptor that refers to the same
kernel resource and has customized permissions.

## Arguments

Expand Down Expand Up @@ -52,3 +59,5 @@ not refer to a process, or is closed.
* JINUE_EBADF if the specified source descriptor is invalid, or is a owner
descriptor, or is closed.
* JINUE_EBADF if the specified destination descriptor is already in use.
* JINUE_EPERM if the specified process descriptor does not have the permission
to bind a descriptor into the process.
34 changes: 25 additions & 9 deletions doc/syscalls/exit-thread.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
# EXIT_THREAD - Exit the Current Thread
# EXIT_THREAD - Terminate the Current Thread

## Description

Exit the current thread.
Terminate the current thread.

## Arguments

Function number (`arg0`) is 12.

```
+----------------------------------------------------------------+
| function = 12 | arg0
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| reserved (0) | arg1
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| reserved (0) | arg2
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| reserved (0) | arg3
+----------------------------------------------------------------+
31 0
```

## Return Value

This function exits the current thread and does not return.
This function terminates the current thread and does not return.

## Errors

This function always succeeds.

## Future Direction

The current system call only affects the current thread. It may be changed or
some other function may be added to allow another thread to be destroyed, in
which case the thread would be specified using a descriptor.
12 changes: 6 additions & 6 deletions doc/syscalls/get-thread-local.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ Function number (`arg0`) is 7.

## Return Value

This function returns the address of the thread-local storage in `arg0`. If this
has not been set for the current thread by a previous call to the Set
Thread-Local Storage system call, then the return value is zero (i.e. the NULL
pointer in C).
This function sets `arg0` to 0 and set the address of the thread-local storage
in `arg1`. If this has not been set for the current thread by a previous call
to [SET_THREAD_LOCAL] (set-thread-local.md) then the address set in `arg1` is
zero (i.e. the NULL pointer in C).

Note that, since this function returns a pointer, it does not follow the usual
convention whereby a negative return value indicates a failure.
Note that since this function returns a pointer, it does not follow the usual
convention where `arg0` is used to return a successful value.

## Errors

Expand Down
54 changes: 54 additions & 0 deletions doc/syscalls/join-thread.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# JOIN_THREAD - Wait for a Thread to Exit

## Description

Wait for a thread to terminate, if it hasn't already.

The target thread must have been started with [START_THREAD](start-thread.md)
and must not be the calling thread. Furthermore, this function must be called
at most once on a given thread since it has been started.

For this operation to succeed, the thread descriptor must have the
[JINUE_PERM_JOIN](../../include/jinue/shared/asm/permissions.h) permission.

## Arguments

Function number (`arg0`) is 21.

The descriptor number for the thread is set in `arg1`.

```
+----------------------------------------------------------------+
| function = 21 | arg0
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| thread descriptor number | arg1
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| reserved (0) | arg2
+----------------------------------------------------------------+
31 0
+----------------------------------------------------------------+
| reserved (0) | arg3
+----------------------------------------------------------------+
31 0
```

## Return Value

On success, this function returns 0 (in `arg0`). On failure, this function
returns -1 and an error number is set (in `arg1`).

## Errors

* JINUE_EBADF if the thread descriptor is invalid, or does not refer to a
thread, or is closed.
* JINUE_ESRCH if the thread has not been started or has already beed joined.
* JINUE_EDEADLK if a thread attempts to join itself.
* JINUE_EPERM if the specified thread descriptor does not have the permission
to join the thread.
5 changes: 5 additions & 0 deletions doc/syscalls/mclone.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

Clone a contiguous memory mapping from one process to another.

For this operation to succeed, the destination process descriptor must have the
[JINUE_PERM_MAP](../../include/jinue/shared/asm/permissions.h) permission.

## Arguments

Function number (`arg0`) is 15.
Expand Down Expand Up @@ -80,3 +83,5 @@ belongs to the kernel.
to a process, or is closed.
* JINUE_EIO if either process no longer exists.
* JINUE_ENOMEM if not enough memory is available to allocate needed page tables.
* JINUE_EPERM if the destination process descriptor does not have the
permission to map memory into the process.
72 changes: 52 additions & 20 deletions doc/syscalls/mint.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,50 @@

## Description

Create a descriptor referencing a kernel resource with specified cookie and
permissions.
Create a descriptor referencing a kernel resource with specified permissions
and cookie.

In order to use this function, the owner descriptor for the resource must be
specified. The owner descriptor is the descriptor that was specified in the
call to the function that created the resource (e.g. CREATE_ENDPOINT).
In order to use this function, the owner descriptor for a kernel resource must
passed as an argument. The owner descriptor for a given kernel resource is the
original descriptor to which the resource was bound when it was created through
the relevant system call (e.g. [CREATE_ENDPOINT](create-endpoint) for an IPC
endpoint). This function binds the same object to a new descriptor with
customized permissions and cookie.

The permissions that can be set on a descriptor depends on the type of kernel
object it refers to. See the
[flag definitions](../../include/jinue/shared/asm/permissions.h) for the
numerical values of the various permission flags.

If the owner descriptor refers to an IPC endpoint, the following permission
flags can be specified:

| Name | Description |
|-----------------------|-----------------------|
| JINUE_PERM_SEND | Send messages |
| JINUE_PERM_RECEIVE | Receive messages |

If the owner descriptor refers to a process, the following permission flags can
be specified:

| Name | Description |
|---------------------------|-------------------------------------------|
| JINUE_PERM_CREATE_THREAD | Create a thread |
| JINUE_PERM_MAP | Map memory into the virtual address space |
| JINUE_PERM_OPEN | Bind a descriptor |

If the owner descriptor refers to a thread, the following permission flags can
be specified:

| Name | Description |
|-------------------|-----------------------------------|
| JINUE_PERM_START | Start the thread |
| JINUE_PERM_JOIN | Wait for the thread to terminate |

Other permission flags are reserved.

For this operation to succeed, the descriptor for the target process must have
the [JINUE_PERM_OPEN](../../include/jinue/shared/asm/permissions.h) permission.

## Arguments

Expand Down Expand Up @@ -47,24 +85,14 @@ The mint arguments structure contains the following fields:
descriptor.
* `fd` descriptor number in the target process in which to place the new
descriptor.
* `perms` the permission flags of the new descriptor (see below).
* `perms` the permission flags of the new descriptor, which must describe a
permissions set appropriate for the type of kernel object the descriptor refers
to. See the [flag definitions](../../include/jinue/shared/asm/permissions.h)
for the numerical values of the permission flags.
* `cookie` the cookie of the new descriptor. This parameter is only meaningful
for references to IPC endpoints and can be set to anything, including zero, for
other resource types.

`perms` must be set to the bitwise or of permission flags that are appropriate
for the type of kernel object to which the owner descriptor refers.

If the owner descriptor refers to an IPC endpoint, the following permission
flags can be specified:

| Value | Name | Description |
|-------|-----------------------|-----------------------------------|
| 1 | JINUE_PERM_SEND | Can be used to send messages |
| 2 | JINUE_PERM_RECEIVE | Can be used to receive messages |

Other permission flags are reserved.

## Return Value

On success, this function returns 0 (in `arg0`). On failure, this function
Expand All @@ -79,4 +107,8 @@ appropriate for the type of kernel object to which the owner descriptor refers.
to a process or is closed.
* JINUE_EBADF if the descriptor specified in the `fd` argument is invalid or is
already in use.
* JINUE_EPERM if the specified descriptor is not the owner descriptor.
* JINUE_EPERM if the specified owner descriptor is not the owner descriptor of
a kernel resource.
* JINUE_EPERM if the specified process descriptor does not have the permission
to bind a descriptor into the process.

Loading

0 comments on commit ce60c73

Please sign in to comment.