summaryrefslogtreecommitdiff
path: root/viengoos/thread.h
blob: f251491287663decec10b048eccc7888fd0b0df2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* thread.h - Thread object interface.
   Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
   Written by Neal H. Walfield <neal@gnu.org>.

   This file is part of the GNU Hurd.

   The GNU Hurd is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 3 of the
   License, or (at your option) any later version.

   The GNU Hurd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef RM_THREAD_H
#define RM_THREAD_H

#include <errno.h>
#include <viengoos/cap.h>
#include <viengoos/thread.h>
#include <hurd/btree.h>
#include "object.h"
#include "list.h"
#include "vm.h"
#include "sys.h"

/* Forward.  */
struct activity;

enum thread_state
  {
    THREAD_SUSPENDED = 0,
    THREAD_RUNNABLE = 1,
    THREAD_RUNNING = 2,
  };

static inline const char *
thread_state_string (enum thread_state state)
{
  switch (state)
    {
    case THREAD_SUSPENDED:
      return "suspended";
    case THREAD_RUNNABLE:
      return "runnable";
    case THREAD_RUNNING:
      return "running";
    default:
      panic ("Unknown thread state!");
    }
}

struct thread
{
  /* User accessible fields.  */

  /* Address space.  */
  struct vg_cap aspace;

  /* The current associated activity.  (Not the activity out of which
     this thread's storage is allocated!)  */
  struct vg_cap activity;

  /* A capability designating a messenger to which to deliver
     exceptions.  */
  struct vg_cap exception_messenger;

  /* A capability the page that contains the thread's UTCB.  */
  struct vg_cap utcb;

  /* Non-user-accessible fields.  */

  /* Whether the thread data structure has been initialized.  */
  uint32_t init : 1;

  /* List of mappings mapped into this thread's hardware address
     space.  */
  hurd_btree_vm_thread_mappings_t vm_mappings;

  struct vg_object_name name;

  /* The last fault.  */
  int last_fault_idx;
  uintptr_t last_fault[4];
  uintptr_t last_fault_ip[4];

  enum thread_state state;
  struct list_node run_queue_node;

  /* The amount of time, in milliseconds, allocated to this thread.  */
  int time;
  uint64_t last_payout;
  uint64_t total_time;

#ifdef THREAD_SYSDEP_MEMBERS
  THREAD_SYSDEP_MEMBERS
#endif
};

LIST_CLASS(thread_queue, struct thread, run_queue_node, true)

/* The hardwired base of the UTCB (2.5GB).  */
#define UTCB_AREA_BASE (0xA0000000)
/* The size of the UTCB.  */
#define UTCB_AREA_SIZE (2 * l4_utcb_area_size ())
/* The hardwired base of the KIP.  */
#define KIP_BASE (UTCB_AREA_BASE + UTCB_AREA_SIZE)

/* Bootstrap the thread subsystem.  */
extern void thread_bootstrap (void);

/* Create a new thread.  Uses the object THREAD to store the thread
   information.  */
extern void thread_init (struct thread *thread);

/* Destroy the thread object THREAD (and the accompanying thread).  */
extern void thread_deinit (struct activity *activity,
			   struct thread *thread);

/* Prepare the thread object THREAD to run.  (Called after bringing a
   thread object into core.)  */
extern void thread_commission (struct thread *thread);

/* Save any state of the thread THREAD and destroy any ephemeral
   resources.  (Called before sending the object to backing
   store.)  */
extern void thread_decommission (struct thread *thread);

/* Perform an exregs on thread THREAD.  CONTROL, SP, IP, EFLAGS and
   USER_HANDLER are as per l4_exchange_regs, however, the caller may
   not set the pager.  */
extern error_t thread_exregs (struct activity *principal,
			      struct thread *thread, uintptr_t control,
			      struct vg_cap aspace,
			      uintptr_t flags, struct vg_cap_properties properties,
			      struct vg_cap activity,
			      struct vg_cap utcb,
			      struct vg_cap exception_messenger,
			      uintptr_t *sp, uintptr_t *ip,
			      uintptr_t *eflags, uintptr_t *user_handle);

/* Deliver the message carried by messenger MESSENGER to thread
   thread.  If thread is not activated, activate the thread.  Returns
   whether the message was delivered or the messenger was enqueued on
   the thread.  */
extern bool thread_activate (struct activity *activity,
			     struct thread *thread,
			     struct messenger *messenger,
			     bool may_block);

/* Send thread THREAD's exception messenger the exception described by
   MESSAGE.  If this would block, silently discards MESSAGE.  */
extern void thread_raise_exception (struct activity *activity,
				    struct thread *thread,
				    struct vg_message *message);

/* Deliver a pending message, if any and if possible.  */
extern void thread_deliver_pending (struct activity *activity,
				    struct thread *thread);

/* Given the thread id THREADID, find the associated thread.  */
extern struct thread *thread_lookup (vg_thread_id_t threadid);

extern void thread_arch_bootstrap (void);

/* Initialize the architecture dependent parts of THREAD, a new thread
   object.  */
extern void thread_arch_init (struct thread *thread);

/* The dual of thread_arch_init.  */
extern void thread_arch_deinit (struct thread *thread);

/* Resume executing the current thread.  */
extern void thread_resume (void);

#endif