sched: implement user-configurable fs and gs segment base addresses
This commit is contained in:
@@ -28,4 +28,6 @@
|
|||||||
static void __used common(void)
|
static void __used common(void)
|
||||||
{
|
{
|
||||||
OFFSET(THREAD_sp, struct thread, tr_sp);
|
OFFSET(THREAD_sp, struct thread, tr_sp);
|
||||||
|
OFFSET(THREAD_fsbase, struct thread, tr_ml.tr_fsbase);
|
||||||
|
OFFSET(THREAD_gsbase, struct thread, tr_ml.tr_gsbase);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MSR_FS_BASE 0xC0000100
|
||||||
#define MSR_GS_BASE 0xC0000101
|
#define MSR_GS_BASE 0xC0000101
|
||||||
#define MSR_KERNEL_GS_BASE 0xC0000102
|
#define MSR_KERNEL_GS_BASE 0xC0000102
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
|
|
||||||
|
struct ml_thread {
|
||||||
|
virt_addr_t tr_gsbase, tr_fsbase;
|
||||||
|
};
|
||||||
|
|
||||||
struct ml_cpu_context;
|
struct ml_cpu_context;
|
||||||
|
|
||||||
/* switch from one thread to another. the stack of the `to` thread must have
|
/* switch from one thread to another. the stack of the `to` thread must have
|
||||||
@@ -28,4 +32,15 @@ extern kern_status_t ml_thread_prepare_user_context(
|
|||||||
const uintptr_t *args,
|
const uintptr_t *args,
|
||||||
size_t nr_args);
|
size_t nr_args);
|
||||||
|
|
||||||
|
extern kern_status_t ml_thread_config_get(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *out,
|
||||||
|
size_t max);
|
||||||
|
extern kern_status_t ml_thread_config_set(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
#include <arch/msr.h>
|
||||||
#include <kernel/machine/cpu.h>
|
#include <kernel/machine/cpu.h>
|
||||||
#include <kernel/machine/thread.h>
|
#include <kernel/machine/thread.h>
|
||||||
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
#define MAX_REG_ARGS 6
|
#define MAX_REG_ARGS 6
|
||||||
#define REG_ARG_0 rdi
|
#define REG_ARG_0 rdi
|
||||||
@@ -77,3 +79,52 @@ extern kern_status_t ml_thread_prepare_user_context(
|
|||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t ml_thread_config_get(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *out,
|
||||||
|
size_t max)
|
||||||
|
{
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t ml_thread_config_set(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
switch (key) {
|
||||||
|
case THREAD_CFG_FSBASE:
|
||||||
|
if (len != sizeof(thread->tr_ml.tr_fsbase)) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->tr_ml.tr_fsbase = *(virt_addr_t *)ptr;
|
||||||
|
if (thread == current_thread()) {
|
||||||
|
wrmsr(MSR_FS_BASE, thread->tr_ml.tr_fsbase);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case THREAD_CFG_GSBASE:
|
||||||
|
if (len != sizeof(thread->tr_ml.tr_gsbase)) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->tr_ml.tr_gsbase = *(virt_addr_t *)ptr;
|
||||||
|
if (thread == current_thread()) {
|
||||||
|
/* we're in the kernel right now, so the user and kernel
|
||||||
|
* gs-base registers are swapped. when we return to
|
||||||
|
* usermode, this value will be swapped back into
|
||||||
|
* the user gs-base register */
|
||||||
|
wrmsr(MSR_KERNEL_GS_BASE, thread->tr_ml.tr_gsbase);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,22 @@ ml_thread_switch:
|
|||||||
push %rax
|
push %rax
|
||||||
push %rcx
|
push %rcx
|
||||||
push %rdx
|
push %rdx
|
||||||
|
|
||||||
|
// set fs-base
|
||||||
|
mov $0xC0000100, %rcx
|
||||||
|
movq THREAD_fsbase(%rsi), %rax
|
||||||
|
movq THREAD_fsbase(%rsi), %rdx
|
||||||
|
shr $32, %rdx
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
// set (kernel) gs-base (it will be swapped back into user-gs-base at
|
||||||
|
// the end of this function)
|
||||||
|
mov $0xC0000102, %rcx
|
||||||
|
movq THREAD_gsbase(%rsi), %rax
|
||||||
|
movq THREAD_gsbase(%rsi), %rdx
|
||||||
|
shr $32, %rdx
|
||||||
|
wrmsr
|
||||||
|
|
||||||
push %rbx
|
push %rbx
|
||||||
pushq $0
|
pushq $0
|
||||||
push %rbp
|
push %rbp
|
||||||
|
|||||||
@@ -56,8 +56,28 @@ extern kern_status_t sys_task_create_thread(
|
|||||||
extern kern_status_t sys_task_get_address_space(
|
extern kern_status_t sys_task_get_address_space(
|
||||||
kern_handle_t task,
|
kern_handle_t task,
|
||||||
kern_handle_t *out);
|
kern_handle_t *out);
|
||||||
|
extern kern_status_t sys_task_config_get(
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *ptr,
|
||||||
|
size_t len);
|
||||||
|
extern kern_status_t sys_task_config_set(
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
extern kern_status_t sys_thread_start(kern_handle_t thread);
|
extern kern_status_t sys_thread_start(kern_handle_t thread);
|
||||||
|
extern kern_status_t sys_thread_config_get(
|
||||||
|
kern_handle_t thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *ptr,
|
||||||
|
size_t len);
|
||||||
|
extern kern_status_t sys_thread_config_set(
|
||||||
|
kern_handle_t thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
extern kern_status_t sys_vm_object_create(
|
extern kern_status_t sys_vm_object_create(
|
||||||
const char *name,
|
const char *name,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef KERNEL_THREAD_H_
|
#ifndef KERNEL_THREAD_H_
|
||||||
#define KERNEL_THREAD_H_
|
#define KERNEL_THREAD_H_
|
||||||
|
|
||||||
|
#include <kernel/machine/thread.h>
|
||||||
#include <kernel/msg.h>
|
#include <kernel/msg.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
#include <kernel/vm-controller.h>
|
#include <kernel/vm-controller.h>
|
||||||
@@ -22,7 +23,7 @@ enum thread_flags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct thread {
|
struct thread {
|
||||||
struct object thr_base;
|
struct object tr_base;
|
||||||
|
|
||||||
enum thread_state tr_state;
|
enum thread_state tr_state;
|
||||||
enum thread_flags tr_flags;
|
enum thread_flags tr_flags;
|
||||||
@@ -38,6 +39,7 @@ struct thread {
|
|||||||
virt_addr_t tr_ip, tr_sp, tr_bp;
|
virt_addr_t tr_ip, tr_sp, tr_bp;
|
||||||
virt_addr_t tr_cpu_user_sp, tr_cpu_kernel_sp;
|
virt_addr_t tr_cpu_user_sp, tr_cpu_kernel_sp;
|
||||||
|
|
||||||
|
struct ml_thread tr_ml;
|
||||||
struct runqueue *tr_rq;
|
struct runqueue *tr_rq;
|
||||||
|
|
||||||
struct queue_entry tr_parent_entry;
|
struct queue_entry tr_parent_entry;
|
||||||
@@ -61,4 +63,17 @@ extern void idle(void);
|
|||||||
extern struct thread *create_kernel_thread(void (*fn)(void));
|
extern struct thread *create_kernel_thread(void (*fn)(void));
|
||||||
extern struct thread *create_idle_thread(void);
|
extern struct thread *create_idle_thread(void);
|
||||||
|
|
||||||
|
extern kern_status_t thread_config_get(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *out,
|
||||||
|
size_t max);
|
||||||
|
extern kern_status_t thread_config_set(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
DEFINE_OBJECT_LOCK_FUNCTION(thread, tr_base)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -60,8 +60,12 @@ SYSCALL_GATE task_self SYS_TASK_SELF 0
|
|||||||
SYSCALL_GATE task_create SYS_TASK_CREATE 5
|
SYSCALL_GATE task_create SYS_TASK_CREATE 5
|
||||||
SYSCALL_GATE task_create_thread SYS_TASK_CREATE_THREAD 6
|
SYSCALL_GATE task_create_thread SYS_TASK_CREATE_THREAD 6
|
||||||
SYSCALL_GATE task_get_address_space SYS_TASK_GET_ADDRESS_SPACE 1
|
SYSCALL_GATE task_get_address_space SYS_TASK_GET_ADDRESS_SPACE 1
|
||||||
|
SYSCALL_GATE task_config_get SYS_TASK_CONFIG_GET 4
|
||||||
|
SYSCALL_GATE task_config_set SYS_TASK_CONFIG_SET 4
|
||||||
|
|
||||||
SYSCALL_GATE thread_start SYS_THREAD_START 1
|
SYSCALL_GATE thread_start SYS_THREAD_START 1
|
||||||
|
SYSCALL_GATE thread_config_get SYS_THREAD_CONFIG_GET 4
|
||||||
|
SYSCALL_GATE thread_config_set SYS_THREAD_CONFIG_SET 4
|
||||||
|
|
||||||
SYSCALL_GATE vm_object_create SYS_VM_OBJECT_CREATE 5
|
SYSCALL_GATE vm_object_create SYS_VM_OBJECT_CREATE 5
|
||||||
SYSCALL_GATE vm_object_read SYS_VM_OBJECT_READ 5
|
SYSCALL_GATE vm_object_read SYS_VM_OBJECT_READ 5
|
||||||
|
|||||||
@@ -23,7 +23,27 @@ extern kern_status_t task_create_thread(
|
|||||||
extern kern_status_t task_get_address_space(
|
extern kern_status_t task_get_address_space(
|
||||||
kern_handle_t task,
|
kern_handle_t task,
|
||||||
kern_handle_t *out);
|
kern_handle_t *out);
|
||||||
|
extern kern_status_t task_config_get(
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *ptr,
|
||||||
|
size_t len);
|
||||||
|
extern kern_status_t task_config_set(
|
||||||
|
kern_handle_t task,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
extern kern_status_t thread_start(kern_handle_t thread);
|
extern kern_status_t thread_start(kern_handle_t thread);
|
||||||
|
extern kern_status_t thread_config_get(
|
||||||
|
kern_handle_t thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *ptr,
|
||||||
|
size_t len);
|
||||||
|
extern kern_status_t thread_config_set(
|
||||||
|
kern_handle_t thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,11 @@
|
|||||||
#define SYS_TASK_CREATE 0x09u
|
#define SYS_TASK_CREATE 0x09u
|
||||||
#define SYS_TASK_CREATE_THREAD 0x0Au
|
#define SYS_TASK_CREATE_THREAD 0x0Au
|
||||||
#define SYS_TASK_GET_ADDRESS_SPACE 0x0Bu
|
#define SYS_TASK_GET_ADDRESS_SPACE 0x0Bu
|
||||||
|
#define SYS_TASK_CONFIG_GET 0x2Au
|
||||||
|
#define SYS_TASK_CONFIG_SET 0x2Bu
|
||||||
#define SYS_THREAD_START 0x0Cu
|
#define SYS_THREAD_START 0x0Cu
|
||||||
|
#define SYS_THREAD_CONFIG_GET 0x2Cu
|
||||||
|
#define SYS_THREAD_CONFIG_SET 0x2Du
|
||||||
#define SYS_VM_OBJECT_CREATE 0x0Du
|
#define SYS_VM_OBJECT_CREATE 0x0Du
|
||||||
#define SYS_VM_OBJECT_READ 0x0Eu
|
#define SYS_VM_OBJECT_READ 0x0Eu
|
||||||
#define SYS_VM_OBJECT_WRITE 0x0Fu
|
#define SYS_VM_OBJECT_WRITE 0x0Fu
|
||||||
|
|||||||
@@ -16,8 +16,17 @@
|
|||||||
#define MAP_ADDRESS_INVALID ((virt_addr_t)0)
|
#define MAP_ADDRESS_INVALID ((virt_addr_t)0)
|
||||||
#define KERN_HANDLE_INVALID ((kern_handle_t)0xFFFFFFFF)
|
#define KERN_HANDLE_INVALID ((kern_handle_t)0xFFFFFFFF)
|
||||||
|
|
||||||
#define KERN_CFG_INVALID 0x00u
|
/* config keys for use with kern_config_get/kern_config_set */
|
||||||
#define KERN_CFG_PAGE_SIZE 0x01u
|
#define KERN_CFG_INVALID 0x00000u
|
||||||
|
#define KERN_CFG_PAGE_SIZE 0x00001u
|
||||||
|
|
||||||
|
/* config keys for use with task_config_get/task_config_set */
|
||||||
|
#define TASK_CFG_INVALID 0x00000u
|
||||||
|
|
||||||
|
/* config keys for use with thread_config_get/thread_config_set */
|
||||||
|
#define THREAD_CFG_INVALID 0x00000u
|
||||||
|
#define THREAD_CFG_FSBASE 0x20001u
|
||||||
|
#define THREAD_CFG_GSBASE 0x20002u
|
||||||
|
|
||||||
/* maximum number of handles that can be sent in a single message */
|
/* maximum number of handles that can be sent in a single message */
|
||||||
#define KERN_MSG_MAX_HANDLES 64
|
#define KERN_MSG_MAX_HANDLES 64
|
||||||
@@ -53,16 +62,20 @@
|
|||||||
|
|
||||||
#define IOVEC(p, len) \
|
#define IOVEC(p, len) \
|
||||||
{ \
|
{ \
|
||||||
.io_base = (virt_addr_t)(p), .io_len = (len), \
|
.io_base = (virt_addr_t)(p), \
|
||||||
|
.io_len = (len), \
|
||||||
}
|
}
|
||||||
#define MSG_HANDLE(mode, value) \
|
#define MSG_HANDLE(mode, value) \
|
||||||
{ \
|
{ \
|
||||||
.hnd_mode = (mode), .hnd_value = (value), \
|
.hnd_mode = (mode), \
|
||||||
|
.hnd_value = (value), \
|
||||||
}
|
}
|
||||||
#define MSG(data, data_count, handles, handles_len) \
|
#define MSG(data, data_count, handles, handles_len) \
|
||||||
{ \
|
{ \
|
||||||
.msg_data = (data), .msg_data_count = (data_count), \
|
.msg_data = (data), \
|
||||||
.msg_handles = (handles), .msg_handles_count = (handles_len), \
|
.msg_data_count = (data_count), \
|
||||||
|
.msg_handles = (handles), \
|
||||||
|
.msg_handles_count = (handles_len), \
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef uintptr_t phys_addr_t;
|
typedef uintptr_t phys_addr_t;
|
||||||
|
|||||||
@@ -2,15 +2,17 @@
|
|||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/machine/thread.h>
|
#include <kernel/machine/thread.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
|
#include <kernel/printk.h>
|
||||||
#include <kernel/task.h>
|
#include <kernel/task.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
|
#include <mango/signal.h>
|
||||||
|
|
||||||
#define THREAD_CAST(p) OBJECT_C_CAST(struct thread, thr_base, &thread_type, p)
|
#define THREAD_CAST(p) OBJECT_C_CAST(struct thread, tr_base, &thread_type, p)
|
||||||
|
|
||||||
static struct object_type thread_type = {
|
static struct object_type thread_type = {
|
||||||
.ob_name = "thread",
|
.ob_name = "thread",
|
||||||
.ob_size = sizeof(struct thread),
|
.ob_size = sizeof(struct thread),
|
||||||
.ob_header_offset = offsetof(struct thread, thr_base),
|
.ob_header_offset = offsetof(struct thread, tr_base),
|
||||||
};
|
};
|
||||||
|
|
||||||
kern_status_t thread_object_type_init(void)
|
kern_status_t thread_object_type_init(void)
|
||||||
@@ -185,3 +187,31 @@ struct thread *create_idle_thread(void)
|
|||||||
|
|
||||||
return thr;
|
return thr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t thread_config_get(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *out,
|
||||||
|
size_t max)
|
||||||
|
{
|
||||||
|
switch (key) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ml_thread_config_get(thread, key, out, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t thread_config_set(
|
||||||
|
struct thread *thread,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
switch (key) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ml_thread_config_set(thread, key, ptr, len);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ static const virt_addr_t syscall_table[] = {
|
|||||||
SYSCALL_TABLE_ENTRY(TASK_CREATE_THREAD, task_create_thread),
|
SYSCALL_TABLE_ENTRY(TASK_CREATE_THREAD, task_create_thread),
|
||||||
SYSCALL_TABLE_ENTRY(TASK_GET_ADDRESS_SPACE, task_get_address_space),
|
SYSCALL_TABLE_ENTRY(TASK_GET_ADDRESS_SPACE, task_get_address_space),
|
||||||
SYSCALL_TABLE_ENTRY(THREAD_START, thread_start),
|
SYSCALL_TABLE_ENTRY(THREAD_START, thread_start),
|
||||||
|
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_GET, thread_config_get),
|
||||||
|
SYSCALL_TABLE_ENTRY(THREAD_CONFIG_SET, thread_config_set),
|
||||||
SYSCALL_TABLE_ENTRY(VM_OBJECT_CREATE, vm_object_create),
|
SYSCALL_TABLE_ENTRY(VM_OBJECT_CREATE, vm_object_create),
|
||||||
SYSCALL_TABLE_ENTRY(VM_OBJECT_READ, vm_object_read),
|
SYSCALL_TABLE_ENTRY(VM_OBJECT_READ, vm_object_read),
|
||||||
SYSCALL_TABLE_ENTRY(VM_OBJECT_WRITE, vm_object_write),
|
SYSCALL_TABLE_ENTRY(VM_OBJECT_WRITE, vm_object_write),
|
||||||
|
|||||||
@@ -287,3 +287,75 @@ kern_status_t sys_thread_start(kern_handle_t thread_handle)
|
|||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t sys_thread_config_get(
|
||||||
|
kern_handle_t thread_handle,
|
||||||
|
kern_config_key_t key,
|
||||||
|
void *ptr,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct task *self = current_task();
|
||||||
|
|
||||||
|
if (!validate_access_w(self, ptr, len)) {
|
||||||
|
return KERN_MEMORY_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *thread_obj;
|
||||||
|
handle_flags_t thread_flags;
|
||||||
|
task_lock_irqsave(self, &flags);
|
||||||
|
kern_status_t status = task_resolve_handle(
|
||||||
|
self,
|
||||||
|
thread_handle,
|
||||||
|
&thread_obj,
|
||||||
|
&thread_flags);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
task_unlock_irqrestore(self, flags);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct thread *thread = thread_cast(thread_obj);
|
||||||
|
task_unlock_irqrestore(self, flags);
|
||||||
|
|
||||||
|
status = thread_config_get(thread, key, ptr, len);
|
||||||
|
|
||||||
|
object_unref(thread_obj);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t sys_thread_config_set(
|
||||||
|
kern_handle_t thread_handle,
|
||||||
|
kern_config_key_t key,
|
||||||
|
const void *ptr,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct task *self = current_task();
|
||||||
|
|
||||||
|
if (!validate_access_w(self, ptr, len)) {
|
||||||
|
return KERN_MEMORY_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *thread_obj;
|
||||||
|
handle_flags_t thread_flags;
|
||||||
|
task_lock_irqsave(self, &flags);
|
||||||
|
kern_status_t status = task_resolve_handle(
|
||||||
|
self,
|
||||||
|
thread_handle,
|
||||||
|
&thread_obj,
|
||||||
|
&thread_flags);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
task_unlock_irqrestore(self, flags);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct thread *thread = thread_cast(thread_obj);
|
||||||
|
task_unlock_irqrestore(self, flags);
|
||||||
|
|
||||||
|
status = thread_config_set(thread, key, ptr, len);
|
||||||
|
|
||||||
|
object_unref(thread_obj);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user