The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/mach/mach_thread.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mach_thread.c,v 1.38 2006/11/16 01:32:44 christos Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.38 2006/11/16 01:32:44 christos Exp $");
   41 
   42 #include <sys/types.h>
   43 #include <sys/param.h>
   44 #include <sys/kernel.h>
   45 #include <sys/systm.h>
   46 #include <sys/signal.h>
   47 #include <sys/lock.h>
   48 #include <sys/queue.h>
   49 #include <sys/proc.h>
   50 #include <sys/resource.h>
   51 #include <sys/resourcevar.h>
   52 #include <sys/sa.h>
   53 #include <sys/savar.h>
   54 
   55 #include <compat/mach/mach_types.h>
   56 #include <compat/mach/mach_message.h>
   57 #include <compat/mach/mach_exec.h>
   58 #include <compat/mach/mach_clock.h>
   59 #include <compat/mach/mach_port.h>
   60 #include <compat/mach/mach_task.h>
   61 #include <compat/mach/mach_thread.h>
   62 #include <compat/mach/mach_errno.h>
   63 #include <compat/mach/mach_services.h>
   64 #include <compat/mach/mach_syscallargs.h>
   65 
   66 int
   67 mach_sys_syscall_thread_switch(struct lwp *l, void *v,
   68     register_t *retval)
   69 {
   70         struct mach_sys_syscall_thread_switch_args /* {
   71                 syscallarg(mach_port_name_t) thread_name;
   72                 syscallarg(int) option;
   73                 syscallarg(mach_msg_timeout_t) option_time;
   74         } */ *uap = v;
   75         int timeout;
   76         struct mach_emuldata *med;
   77 
   78         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
   79         timeout = SCARG(uap, option_time) * hz / 1000;
   80 
   81         /*
   82          * The day we will be able to find out the struct proc from
   83          * the port number, try to use preempt() to call the right thread.
   84          * [- but preempt() is for _involuntary_ context switches.]
   85          */
   86         switch(SCARG(uap, option)) {
   87         case MACH_SWITCH_OPTION_NONE:
   88                 yield();
   89                 break;
   90 
   91         case MACH_SWITCH_OPTION_WAIT:
   92                 med->med_thpri = 1;
   93                 while (med->med_thpri != 0)
   94                         (void)tsleep(&med->med_thpri, PZERO|PCATCH,
   95                             "thread_switch", timeout);
   96                 break;
   97 
   98         case MACH_SWITCH_OPTION_DEPRESS:
   99         case MACH_SWITCH_OPTION_IDLE:
  100                 /* Use a callout to restore the priority after depression? */
  101                 med->med_thpri = l->l_priority;
  102                 l->l_priority = MAXPRI;
  103                 break;
  104 
  105         default:
  106                 uprintf("mach_sys_syscall_thread_switch(): unknown option %d\n",                    SCARG(uap, option));
  107                 break;
  108         }
  109         return 0;
  110 }
  111 
  112 int
  113 mach_sys_swtch_pri(struct lwp *l, void *v, register_t *retval)
  114 {
  115 #if 0   /* pri is not used yet */
  116         struct mach_sys_swtch_pri_args /* {
  117                 syscallarg(int) pri;
  118         } */ *uap = v;
  119 #endif
  120         int s;
  121 
  122         /*
  123          * Copied from preempt(9). We cannot just call preempt
  124          * because we want to return mi_switch(9) return value.
  125          */
  126         SCHED_LOCK(s);
  127         l->l_priority = l->l_usrpri;
  128         l->l_stat = LSRUN;
  129         setrunqueue(l);
  130         l->l_proc->p_stats->p_ru.ru_nivcsw++;
  131         *retval = mi_switch(l, NULL);
  132         SCHED_ASSERT_UNLOCKED();
  133         splx(s);
  134         if ((l->l_flag & L_SA) != 0 && *retval != 0)
  135                 sa_preempt(l);
  136 
  137         return 0;
  138 }
  139 
  140 int
  141 mach_sys_swtch(struct lwp *l, void *v, register_t *retval)
  142 {
  143         struct mach_sys_swtch_pri_args cup;
  144 
  145         SCARG(&cup, pri) = 0;
  146 
  147         return mach_sys_swtch_pri(l, &cup, retval);
  148 }
  149 
  150 
  151 int
  152 mach_thread_policy(args)
  153         struct mach_trap_args *args;
  154 {
  155         mach_thread_policy_request_t *req = args->smsg;
  156         mach_thread_policy_reply_t *rep = args->rmsg;
  157         size_t *msglen = args->rsize;
  158         int end_offset;
  159 
  160         /* Sanity check req_count */
  161         end_offset = req->req_count +
  162                      (sizeof(req->req_setlimit) / sizeof(req->req_base[0]));
  163         if (MACH_REQMSG_OVERFLOW(args, req->req_base[end_offset]))
  164                 return mach_msg_error(args, EINVAL);
  165 
  166         uprintf("Unimplemented mach_thread_policy\n");
  167 
  168         *msglen = sizeof(*rep);
  169         mach_set_header(rep, req, *msglen);
  170 
  171         rep->rep_retval = 0;
  172 
  173         mach_set_trailer(rep, *msglen);
  174 
  175         return 0;
  176 }
  177 
  178 /* XXX it might be possible to use this on another task */
  179 int
  180 mach_thread_create_running(args)
  181         struct mach_trap_args *args;
  182 {
  183         mach_thread_create_running_request_t *req = args->smsg;
  184         mach_thread_create_running_reply_t *rep = args->rmsg;
  185         size_t *msglen = args->rsize;
  186         struct lwp *l = args->l;
  187         struct proc *p = l->l_proc;
  188         struct mach_create_thread_child_args mctc;
  189         struct mach_right *child_mr;
  190         struct mach_lwp_emuldata *mle;
  191         vaddr_t uaddr;
  192         int flags;
  193         int error;
  194         int inmem;
  195         int s;
  196         int end_offset;
  197 
  198         /* Sanity check req_count */
  199         end_offset = req->req_count;
  200         if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset]))
  201                 return mach_msg_error(args, EINVAL);
  202 
  203         /*
  204          * Prepare the data we want to transmit to the child.
  205          */
  206         mctc.mctc_flavor = req->req_flavor;
  207         mctc.mctc_oldlwp = l;
  208         mctc.mctc_child_done = 0;
  209         mctc.mctc_state = req->req_state;
  210 
  211         inmem = uvm_uarea_alloc(&uaddr);
  212         if (__predict_false(uaddr == 0))
  213                 return (ENOMEM);
  214 
  215         flags = 0;
  216         if ((error = newlwp(l, p, uaddr, inmem, flags, NULL, 0,
  217             mach_create_thread_child, (void *)&mctc, &mctc.mctc_lwp)) != 0)
  218                 return mach_msg_error(args, error);
  219 
  220         /*
  221          * Make the child runnable.
  222          */
  223         SCHED_LOCK(s);
  224         mctc.mctc_lwp->l_private = 0;
  225         mctc.mctc_lwp->l_stat = LSRUN;
  226         setrunqueue(mctc.mctc_lwp);
  227         p->p_nrlwps++;
  228         SCHED_UNLOCK(s);
  229 
  230         /*
  231          * Get the child's kernel port
  232          */
  233         mle = mctc.mctc_lwp->l_emuldata;
  234         child_mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0);
  235 
  236         /*
  237          * The child relies on some values in mctc, so we should not
  238          * exit until it is finished with it. We catch signals so that
  239          * the process can be killed with kill -9, but we loop to avoid
  240          * spurious wakeups due to other signals.
  241          */
  242         while(mctc.mctc_child_done == 0)
  243                 (void)tsleep(&mctc.mctc_child_done,
  244                     PZERO|PCATCH, "mach_thread", 0);
  245 
  246         *msglen = sizeof(*rep);
  247         mach_set_header(rep, req, *msglen);
  248         mach_add_port_desc(rep, child_mr->mr_name);
  249         mach_set_trailer(rep, *msglen);
  250 
  251         return 0;
  252 }
  253 
  254 int
  255 mach_thread_info(args)
  256         struct mach_trap_args *args;
  257 {
  258         mach_thread_info_request_t *req = args->smsg;
  259         mach_thread_info_reply_t *rep = args->rmsg;
  260         size_t *msglen = args->rsize;
  261         struct lwp *l = args->l;
  262         struct lwp *tl = args->tl;
  263         struct proc *tp = tl->l_proc;
  264 
  265         /* Sanity check req->req_count */
  266         if (req->req_count > 12)
  267                 return mach_msg_error(args, EINVAL);
  268 
  269         rep->rep_count = req->req_count;
  270 
  271         *msglen = sizeof(*rep) + ((req->req_count - 12) * sizeof(int));
  272         mach_set_header(rep, req, *msglen);
  273 
  274         switch (req->req_flavor) {
  275         case MACH_THREAD_BASIC_INFO: {
  276                 struct mach_thread_basic_info *tbi;
  277 
  278                 if (req->req_count != (sizeof(*tbi) / sizeof(int))) /* 10 */
  279                         return mach_msg_error(args, EINVAL);
  280 
  281                 tbi = (struct mach_thread_basic_info *)rep->rep_out;
  282                 tbi->user_time.seconds = tp->p_uticks * hz / 1000000;
  283                 tbi->user_time.microseconds =
  284                     (tp->p_uticks) * hz - tbi->user_time.seconds;
  285                 tbi->system_time.seconds = tp->p_sticks * hz / 1000000;
  286                 tbi->system_time.microseconds =
  287                     (tp->p_sticks) * hz - tbi->system_time.seconds;
  288                 tbi->cpu_usage = tp->p_pctcpu;
  289                 tbi->policy = MACH_THREAD_STANDARD_POLICY;
  290 
  291                 /* XXX this is not very accurate */
  292                 tbi->run_state = MACH_TH_STATE_RUNNING;
  293                 tbi->flags = 0;
  294                 switch (l->l_stat) {
  295                 case LSRUN:
  296                         tbi->run_state = MACH_TH_STATE_RUNNING;
  297                         break;
  298                 case LSSTOP:
  299                         tbi->run_state = MACH_TH_STATE_STOPPED;
  300                         break;
  301                 case LSSLEEP:
  302                         tbi->run_state = MACH_TH_STATE_WAITING;
  303                         break;
  304                 case LSIDL:
  305                         tbi->run_state = MACH_TH_STATE_RUNNING;
  306                         tbi->flags = MACH_TH_FLAGS_IDLE;
  307                         break;
  308                 default:
  309                         break;
  310                 }
  311 
  312                 tbi->suspend_count = 0;
  313                 tbi->sleep_time = tl->l_slptime;
  314                 break;
  315         }
  316 
  317         case MACH_THREAD_SCHED_TIMESHARE_INFO: {
  318                 struct mach_policy_timeshare_info *pti;
  319 
  320                 if (req->req_count != (sizeof(*pti) / sizeof(int))) /* 5 */
  321                         return mach_msg_error(args, EINVAL);
  322 
  323                 pti = (struct mach_policy_timeshare_info *)rep->rep_out;
  324 
  325                 pti->max_priority = tl->l_usrpri;
  326                 pti->base_priority = tl->l_usrpri;
  327                 pti->cur_priority = tl->l_usrpri;
  328                 pti->depressed = 0;
  329                 pti->depress_priority = tl->l_usrpri;
  330                 break;
  331         }
  332 
  333         case MACH_THREAD_SCHED_RR_INFO:
  334         case MACH_THREAD_SCHED_FIFO_INFO:
  335                 uprintf("Unimplemented thread_info flavor %d\n",
  336                     req->req_flavor);
  337         default:
  338                 return mach_msg_error(args, EINVAL);
  339                 break;
  340         }
  341 
  342         mach_set_trailer(rep, *msglen);
  343 
  344         return 0;
  345 }
  346 
  347 int
  348 mach_thread_get_state(args)
  349         struct mach_trap_args *args;
  350 {
  351         mach_thread_get_state_request_t *req = args->smsg;
  352         mach_thread_get_state_reply_t *rep = args->rmsg;
  353         size_t *msglen = args->rsize;
  354         struct lwp *tl = args->tl;
  355         int error;
  356         int size;
  357 
  358         /* Sanity check req->req_count */
  359         if (req->req_count > 144)
  360                 return mach_msg_error(args, EINVAL);
  361 
  362         if ((error = mach_thread_get_state_machdep(tl,
  363             req->req_flavor, &rep->rep_state, &size)) != 0)
  364                 return mach_msg_error(args, error);
  365 
  366         rep->rep_count = size / sizeof(int);
  367         *msglen = sizeof(*rep) + ((req->req_count - 144) * sizeof(int));
  368         mach_set_header(rep, req, *msglen);
  369         mach_set_trailer(rep, *msglen);
  370 
  371         return 0;
  372 }
  373 
  374 int
  375 mach_thread_set_state(args)
  376         struct mach_trap_args *args;
  377 {
  378         mach_thread_set_state_request_t *req = args->smsg;
  379         mach_thread_set_state_reply_t *rep = args->rmsg;
  380         size_t *msglen = args->rsize;
  381         struct lwp *tl = args->tl;
  382         int error;
  383         int end_offset;
  384 
  385         /* Sanity check req_count */
  386         end_offset = req->req_count;
  387         if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset]))
  388                 return mach_msg_error(args, EINVAL);
  389 
  390         if ((error = mach_thread_set_state_machdep(tl,
  391             req->req_flavor, &req->req_state)) != 0)
  392                 return mach_msg_error(args, error);
  393 
  394         *msglen = sizeof(*rep);
  395         mach_set_header(rep, req, *msglen);
  396 
  397         rep->rep_retval = 0;
  398 
  399         mach_set_trailer(rep, *msglen);
  400 
  401         return 0;
  402 }
  403 
  404 int
  405 mach_thread_suspend(args)
  406         struct mach_trap_args *args;
  407 {
  408         mach_thread_suspend_request_t *req = args->smsg;
  409         mach_thread_suspend_reply_t *rep = args->rmsg;
  410         size_t *msglen = args->rsize;
  411         struct lwp *l = args->l;
  412         struct lwp *tl = args->tl;
  413         int error;
  414 
  415         error = lwp_suspend(l, tl);
  416 
  417         *msglen = sizeof(*rep);
  418         mach_set_header(rep, req, *msglen);
  419         rep->rep_retval = native_to_mach_errno[error];
  420         mach_set_trailer(rep, *msglen);
  421 
  422         return 0;
  423 }
  424 
  425 int
  426 mach_thread_resume(args)
  427         struct mach_trap_args *args;
  428 {
  429         mach_thread_resume_request_t *req = args->smsg;
  430         mach_thread_resume_reply_t *rep = args->rmsg;
  431         size_t *msglen = args->rsize;
  432         struct lwp *tl = args->tl;
  433 
  434         lwp_continue(tl);
  435 
  436         *msglen = sizeof(*rep);
  437         mach_set_header(rep, req, *msglen);
  438         rep->rep_retval = 0;
  439         mach_set_trailer(rep, *msglen);
  440 
  441         return 0;
  442 }
  443 
  444 int
  445 mach_thread_abort(args)
  446         struct mach_trap_args *args;
  447 {
  448         mach_thread_abort_request_t *req = args->smsg;
  449         mach_thread_abort_reply_t *rep = args->rmsg;
  450         size_t *msglen = args->rsize;
  451         struct lwp *tl = args->tl;
  452 
  453         lwp_exit(tl);
  454 
  455         *msglen = sizeof(*rep);
  456         mach_set_header(rep, req, *msglen);
  457         rep->rep_retval = 0;
  458         mach_set_trailer(rep, *msglen);
  459 
  460         return 0;
  461 }
  462 
  463 int
  464 mach_thread_set_policy(args)
  465         struct mach_trap_args *args;
  466 {
  467         mach_thread_set_policy_request_t *req = args->smsg;
  468         mach_thread_set_policy_reply_t *rep = args->rmsg;
  469         size_t *msglen = args->rsize;
  470         struct lwp *tl = args->tl;
  471         mach_port_t mn;
  472         struct mach_right *mr;
  473         int limit_count_offset, limit_offset;
  474         int limit_count;
  475         int *limit;
  476 
  477         limit_count_offset = req->req_base_count;
  478         if (MACH_REQMSG_OVERFLOW(args, req->req_base[limit_count_offset]))
  479                 return mach_msg_error(args, EINVAL);
  480 
  481         limit_count = req->req_base[limit_count_offset];
  482         limit_offset = limit_count_offset +
  483             (sizeof(req->req_limit_count) / sizeof(req->req_base[0]));
  484         limit = &req->req_base[limit_offset];
  485         if (MACH_REQMSG_OVERFLOW(args, limit[limit_count]))
  486                 return mach_msg_error(args, EINVAL);
  487 
  488         mn = req->req_pset.name;
  489         if ((mr = mach_right_check(mn, tl, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  490                 return mach_msg_error(args, EINVAL);
  491 
  492         *msglen = sizeof(*rep);
  493         mach_set_header(rep, req, *msglen);
  494         rep->rep_retval = 0;
  495         mach_set_trailer(rep, *msglen);
  496 
  497         return 0;
  498 }
  499 

Cache object: 2bf8d1746833d034423d4f4f21dd67fb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.