| 189 | } |
| 190 | |
| 191 | int |
| 192 | thread_create(struct thread *td, struct rtprio *rtp, |
| 193 | int (*initialize_thread)(struct thread *, void *), void *thunk) |
| 194 | { |
| 195 | struct thread *newtd; |
| 196 | struct proc *p; |
| 197 | int error; |
| 198 | |
| 199 | p = td->td_proc; |
| 200 | |
| 201 | if (rtp != NULL) { |
| 202 | switch(rtp->type) { |
| 203 | case RTP_PRIO_REALTIME: |
| 204 | case RTP_PRIO_FIFO: |
| 205 | /* Only root can set scheduler policy */ |
| 206 | if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0) |
| 207 | return (EPERM); |
| 208 | if (rtp->prio > RTP_PRIO_MAX) |
| 209 | return (EINVAL); |
| 210 | break; |
| 211 | case RTP_PRIO_NORMAL: |
| 212 | rtp->prio = 0; |
| 213 | break; |
| 214 | default: |
| 215 | return (EINVAL); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | #ifdef RACCT |
| 220 | if (racct_enable) { |
| 221 | PROC_LOCK(p); |
| 222 | error = racct_add(p, RACCT_NTHR, 1); |
| 223 | PROC_UNLOCK(p); |
| 224 | if (error != 0) |
| 225 | return (EPROCLIM); |
| 226 | } |
| 227 | #endif |
| 228 | |
| 229 | /* Initialize our td */ |
| 230 | error = kern_thr_alloc(p, 0, &newtd); |
| 231 | if (error) |
| 232 | goto fail; |
| 233 | |
| 234 | cpu_copy_thread(newtd, td); |
| 235 | |
| 236 | bzero(&newtd->td_startzero, |
| 237 | __rangeof(struct thread, td_startzero, td_endzero)); |
| 238 | bcopy(&td->td_startcopy, &newtd->td_startcopy, |
| 239 | __rangeof(struct thread, td_startcopy, td_endcopy)); |
| 240 | newtd->td_proc = td->td_proc; |
| 241 | newtd->td_rb_list = newtd->td_rbp_list = newtd->td_rb_inact = 0; |
| 242 | thread_cow_get(newtd, td); |
| 243 | |
| 244 | error = initialize_thread(newtd, thunk); |
| 245 | if (error != 0) { |
| 246 | thread_cow_free(newtd); |
| 247 | thread_free(newtd); |
| 248 | goto fail; |