123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- #include <common/kthread.h>
- #include <common/glib.h>
- #include <common/spinlock.h>
- #include <sched/sched.h>
- #include <debug/bug.h>
- #include <time/sleep.h>
- static spinlock_t __kthread_create_lock;
- static struct List kthread_create_list;
- struct process_control_block *kthreadd_pcb = NULL;
- enum KTHREAD_BITS
- {
- KTHREAD_IS_PER_CPU = 0,
- KTHREAD_SHOULD_STOP,
- KTHREAD_SHOULD_PARK,
- };
- struct kthread_create_info_t
- {
-
- int (*thread_fn)(void *data);
- void *data;
- int node;
-
- struct process_control_block *result;
- struct List list;
- };
- struct kthread_info_t
- {
- uint64_t flags;
- uint32_t cpu;
- int result;
- int (*thread_fn)(void *);
- void *data;
-
- bool exited;
- char *full_name;
- };
- static inline struct kthread_info_t *to_kthread(struct process_control_block *pcb)
- {
- WARN_ON(!(pcb->flags & PF_KTHREAD));
- return pcb->worker_private;
- }
- static struct process_control_block *__kthread_create_on_node(int (*thread_fn)(void *data), void *data,
- int node,
- const char name_fmt[], va_list args)
- {
- struct process_control_block *pcb = NULL;
- struct kthread_create_info_t *create = kzalloc(sizeof(struct kthread_create_info_t), 0);
- if (create == NULL)
- return ERR_PTR(-ENOMEM);
- create->thread_fn = thread_fn;
- create->data = data;
- create->node = node;
- create->result = NULL;
- list_init(&create->list);
- spin_lock(&__kthread_create_lock);
- list_append(&kthread_create_list, &create->list);
- spin_unlock(&__kthread_create_lock);
- kdebug("to wakeup kthread daemon..., current preempt=%d, rflags=%#018lx", current_pcb->preempt_count, get_rflags());
- while (kthreadd_pcb == NULL)
- ;
-
- process_wakeup_immediately(kthreadd_pcb);
-
-
- while (create->result == NULL)
- pause();
-
- pcb = create->result;
- if (!IS_ERR(create->result))
- {
-
- }
- kfree(create);
- return pcb;
- }
- void kthread_exit(long result)
- {
- struct kthread_info_t *kt = to_kthread(current_pcb);
- kt->result = result;
- kt->exited = true;
- process_do_exit(0);
- }
- struct process_control_block *kthread_create_on_node(int (*thread_fn)(void *data), void *data,
- int node,
- const char name_fmt[], ...)
- {
- struct process_control_block *pcb;
- va_list args;
- va_start(args, name_fmt);
- pcb = __kthread_create_on_node(thread_fn, data, node, name_fmt, args);
- va_end(args);
- return pcb;
- }
- static int kthread(void *_create)
- {
- struct kthread_create_info_t *create = _create;
-
- int (*thread_fn)(void *data) = create->thread_fn;
- void *data = create->data;
- int retval = 0;
- struct kthread_info_t *self = to_kthread(current_pcb);
- self->thread_fn = thread_fn;
- self->data = data;
-
-
-
- current_pcb->state = PROC_UNINTERRUPTIBLE;
-
- create->result = current_pcb;
- current_pcb->state &= ~PROC_RUNNING;
-
- sched();
- retval = -EINTR;
-
- if (!(self->flags & (1 << KTHREAD_SHOULD_STOP)))
- {
- retval = thread_fn(data);
- }
- kthread_exit(retval);
- }
- static void __create_kthread(struct kthread_create_info_t *create)
- {
- pid_t pid = kernel_thread(kthread, create, CLONE_FS | CLONE_SIGNAL);
- if (IS_ERR((void *)pid))
- {
-
- create->result = (struct process_control_block *)pid;
- }
- }
- int kthreadd(void *unused)
- {
- kinfo("kthread daemon started!");
- struct process_control_block *pcb = current_pcb;
- kthreadd_pcb = current_pcb;
- current_pcb->flags |= PF_NOFREEZE;
- for (;;)
- {
- current_pcb->state = PROC_INTERRUPTIBLE;
-
- if (list_empty(&kthread_create_list))
- sched();
- spin_lock(&__kthread_create_lock);
-
- while (!list_empty(&kthread_create_list))
- {
-
- struct kthread_create_info_t *create = container_of(kthread_create_list.next, struct kthread_create_info_t, list);
- list_del_init(&create->list);
- spin_unlock(&__kthread_create_lock);
- __create_kthread(create);
- spin_lock(&__kthread_create_lock);
- }
- spin_unlock(&__kthread_create_lock);
- }
- }
- bool kthread_should_stop(void)
- {
- struct kthread_info_t *self = to_kthread(current_pcb);
- if (self->flags & (1 << KTHREAD_SHOULD_STOP))
- return true;
- return false;
- }
- int kthread_stop(struct process_control_block *pcb)
- {
- int retval;
- struct kthread_info_t *target = to_kthread(pcb);
- target->flags |= (1 << KTHREAD_SHOULD_STOP);
- process_wakeup(pcb);
-
-
- while (target->exited == false)
- usleep(5000);
- retval = target->result;
-
- process_exit_mm(pcb);
- process_release_pcb(pcb);
- return retval;
- }
- bool kthread_set_worker_private(struct process_control_block *pcb)
- {
- if (WARN_ON_ONCE(to_kthread(pcb)))
- return false;
- struct kthread_info_t *kt = kzalloc(sizeof(struct kthread_info_t), 0);
- if (kt == NULL)
- return false;
- pcb->worker_private = kt;
- return true;
- }
- int kthread_mechanism_init()
- {
- kinfo("Initializing kthread mechanism...");
- spin_init(&__kthread_create_lock);
- list_init(&kthread_create_list);
-
- kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_SIGNAL);
- return 0;
- }
|