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.34.2.1 2005/10/04 22:08:11 tron 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.34.2.1 2005/10/04 22:08:11 tron 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(l, v, retval)
   68         struct lwp *l;
   69         void *v;
   70         register_t *retval;
   71 {
   72         struct mach_sys_syscall_thread_switch_args /* {
   73                 syscallarg(mach_port_name_t) thread_name;
   74                 syscallarg(int) option;
   75                 syscallarg(mach_msg_timeout_t) option_time;
   76         } */ *uap = v;
   77         int timeout;
   78         struct mach_emuldata *med;
   79 
   80         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
   81         timeout = SCARG(uap, option_time) * hz / 1000;
   82 
   83         /*
   84          * The day we will be able to find out the struct proc from
   85          * the port number, try to use preempt() to call the right thread.
   86          * [- but preempt() is for _involuntary_ context switches.]
   87          */
   88         switch(SCARG(uap, option)) {
   89         case MACH_SWITCH_OPTION_NONE:
   90                 yield();
   91                 break;
   92 
   93         case MACH_SWITCH_OPTION_WAIT:
   94                 med->med_thpri = 1;
   95                 while (med->med_thpri != 0)
   96                         (void)tsleep(&med->med_thpri, PZERO|PCATCH,
   97                             "thread_switch", timeout);
   98                 break;
   99 
  100         case MACH_SWITCH_OPTION_DEPRESS:
  101         case MACH_SWITCH_OPTION_IDLE:
  102                 /* Use a callout to restore the priority after depression? */
  103                 med->med_thpri = l->l_priority;
  104                 l->l_priority = MAXPRI;
  105                 break;
  106 
  107         default:
  108                 uprintf("mach_sys_syscall_thread_switch(): unknown option %d\n",                    SCARG(uap, option));
  109                 break;
  110         }
  111         return 0;
  112 }
  113 
  114 int
  115 mach_sys_swtch_pri(l, v, retval)
  116         struct lwp *l;
  117         void *v;
  118         register_t *retval;
  119 {
  120 #if 0   /* pri is not used yet */
  121         struct mach_sys_swtch_pri_args /* {
  122                 syscallarg(int) pri;
  123         } */ *uap = v;
  124 #endif
  125         int s;
  126 
  127         /*
  128          * Copied from preempt(9). We cannot just call preempt
  129          * because we want to return mi_switch(9) return value.
  130          */
  131         SCHED_LOCK(s);
  132         l->l_priority = l->l_usrpri;
  133         l->l_stat = LSRUN;
  134         setrunqueue(l);
  135         l->l_proc->p_stats->p_ru.ru_nivcsw++;
  136         *retval = mi_switch(l, NULL);
  137         SCHED_ASSERT_UNLOCKED();
  138         splx(s);
  139         if ((l->l_flag & L_SA) != 0 && *retval != 0)
  140                 sa_preempt(l);
  141 
  142         return 0;
  143 }
  144 
  145 int
  146 mach_sys_swtch(l, v, retval)
  147         struct lwp *l;
  148         void *v;
  149         register_t *retval;
  150 {
  151         struct mach_sys_swtch_pri_args cup;
  152 
  153         SCARG(&cup, pri) = 0;
  154 
  155         return mach_sys_swtch_pri(l, &cup, retval);
  156 }
  157 
  158 
  159 int
  160 mach_thread_policy(args)
  161         struct mach_trap_args *args;
  162 {
  163         mach_thread_policy_request_t *req = args->smsg;
  164         mach_thread_policy_reply_t *rep = args->rmsg;
  165         size_t *msglen = args->rsize;
  166         int end_offset;
  167 
  168         /* Sanity check req_count */
  169         end_offset = req->req_count +
  170                      (sizeof(req->req_setlimit) / sizeof(req->req_base[0]));
  171         if (MACH_REQMSG_OVERFLOW(args, req->req_base[end_offset]))
  172                 return mach_msg_error(args, EINVAL);
  173 
  174         uprintf("Unimplemented mach_thread_policy\n");
  175 
  176         *msglen = sizeof(*rep);
  177         mach_set_header(rep, req, *msglen);
  178 
  179         rep->rep_retval = 0;
  180 
  181         mach_set_trailer(rep, *msglen);
  182 
  183         return 0;
  184 }
  185 
  186 /* XXX it might be possible to use this on another task */
  187 int
  188 mach_thread_create_running(args)
  189         struct mach_trap_args *args;
  190 {
  191         mach_thread_create_running_request_t *req = args->smsg;
  192         mach_thread_create_running_reply_t *rep = args->rmsg;
  193         size_t *msglen = args->rsize;
  194         struct lwp *l = args->l;
  195         struct proc *p = l->l_proc;
  196         struct mach_create_thread_child_args mctc;
  197         struct mach_right *child_mr;
  198         struct mach_lwp_emuldata *mle;
  199         vaddr_t uaddr;
  200         int flags;
  201         int error;
  202         int inmem;
  203         int s;
  204         int end_offset;
  205 
  206         /* Sanity check req_count */
  207         end_offset = req->req_count;
  208         if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset]))
  209                 return mach_msg_error(args, EINVAL);
  210 
  211         /*
  212          * Prepare the data we want to transmit to the child.
  213          */
  214         mctc.mctc_flavor = req->req_flavor;
  215         mctc.mctc_oldlwp = l;
  216         mctc.mctc_child_done = 0;
  217         mctc.mctc_state = req->req_state;
  218 
  219         inmem = uvm_uarea_alloc(&uaddr);
  220         if (__predict_false(uaddr == 0))
  221                 return (ENOMEM);
  222 
  223         flags = 0;
  224         if ((error = newlwp(l, p, uaddr, inmem, flags, NULL, 0,
  225             mach_create_thread_child, (void *)&mctc, &mctc.mctc_lwp)) != 0)
  226                 return mach_msg_error(args, error);
  227 
  228         /*
  229          * Make the child runnable.
  230          */
  231         SCHED_LOCK(s);
  232         mctc.mctc_lwp->l_private = 0;
  233         mctc.mctc_lwp->l_stat = LSRUN;
  234         setrunqueue(mctc.mctc_lwp);
  235         p->p_nrlwps++;
  236         SCHED_UNLOCK(s);
  237 
  238         /*
  239          * Get the child's kernel port
  240          */
  241         mle = mctc.mctc_lwp->l_emuldata;
  242         child_mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0);
  243 
  244         /*
  245          * The child relies on some values in mctc, so we should not
  246          * exit until it is finished with it. We catch signals so that
  247          * the process can be killed with kill -9, but we loop to avoid
  248          * spurious wakeups due to other signals.
  249          */
  250         while(mctc.mctc_child_done == 0)
  251                 (void)tsleep(&mctc.mctc_child_done,
  252                     PZERO|PCATCH, "mach_thread", 0);
  253 
  254         *msglen = sizeof(*rep);
  255         mach_set_header(rep, req, *msglen);
  256         mach_add_port_desc(rep, child_mr->mr_name);
  257         mach_set_trailer(rep, *msglen);
  258 
  259         return 0;
  260 }
  261 
  262 int
  263 mach_thread_info(args)
  264         struct mach_trap_args *args;
  265 {
  266         mach_thread_info_request_t *req = args->smsg;
  267         mach_thread_info_reply_t *rep = args->rmsg;
  268         size_t *msglen = args->rsize;
  269         struct lwp *l = args->l;
  270         struct lwp *tl = args->tl;
  271         struct proc *tp = tl->l_proc;
  272 
  273         /* Sanity check req->req_count */
  274         if (req->req_count > 12)
  275                 return mach_msg_error(args, EINVAL);
  276 
  277         rep->rep_count = req->req_count;
  278 
  279         *msglen = sizeof(*rep) + ((req->req_count - 12) * sizeof(int));
  280         mach_set_header(rep, req, *msglen);
  281 
  282         switch (req->req_flavor) {
  283         case MACH_THREAD_BASIC_INFO: {
  284                 struct mach_thread_basic_info *tbi;
  285 
  286                 if (req->req_count != (sizeof(*tbi) / sizeof(int))) /* 10 */
  287                         return mach_msg_error(args, EINVAL);
  288 
  289                 tbi = (struct mach_thread_basic_info *)rep->rep_out;
  290                 tbi->user_time.seconds = tp->p_uticks * hz / 1000000;
  291                 tbi->user_time.microseconds =
  292                     (tp->p_uticks) * hz - tbi->user_time.seconds;
  293                 tbi->system_time.seconds = tp->p_sticks * hz / 1000000;
  294                 tbi->system_time.microseconds =
  295                     (tp->p_sticks) * hz - tbi->system_time.seconds;
  296                 tbi->cpu_usage = tp->p_pctcpu;
  297                 tbi->policy = MACH_THREAD_STANDARD_POLICY;
  298 
  299                 /* XXX this is not very accurate */
  300                 tbi->run_state = MACH_TH_STATE_RUNNING;
  301                 tbi->flags = 0;
  302                 switch (l->l_stat) {
  303                 case LSRUN:
  304                         tbi->run_state = MACH_TH_STATE_RUNNING;
  305                         break;
  306                 case LSSTOP:
  307                         tbi->run_state = MACH_TH_STATE_STOPPED;
  308                         break;
  309                 case LSSLEEP:
  310                         tbi->run_state = MACH_TH_STATE_WAITING;
  311                         break;
  312                 case LSIDL:
  313                         tbi->run_state = MACH_TH_STATE_RUNNING;
  314                         tbi->flags = MACH_TH_FLAGS_IDLE;
  315                         break;
  316                 default:
  317                         break;
  318                 }
  319 
  320                 tbi->suspend_count = 0;
  321                 tbi->sleep_time = tl->l_slptime;
  322                 break;
  323         }
  324 
  325         case MACH_THREAD_SCHED_TIMESHARE_INFO: {
  326                 struct mach_policy_timeshare_info *pti;
  327 
  328                 if (req->req_count != (sizeof(*pti) / sizeof(int))) /* 5 */
  329                         return mach_msg_error(args, EINVAL);
  330 
  331                 pti = (struct mach_policy_timeshare_info *)rep->rep_out;
  332 
  333                 pti->max_priority = tl->l_usrpri;
  334                 pti->base_priority = tl->l_usrpri;
  335                 pti->cur_priority = tl->l_usrpri;
  336                 pti->depressed = 0;
  337                 pti->depress_priority = tl->l_usrpri;
  338                 break;
  339         }
  340 
  341         case MACH_THREAD_SCHED_RR_INFO:
  342         case MACH_THREAD_SCHED_FIFO_INFO:
  343                 uprintf("Unimplemented thread_info flavor %d\n",
  344                     req->req_flavor);
  345         default:
  346                 return mach_msg_error(args, EINVAL);
  347                 break;
  348         }
  349 
  350         mach_set_trailer(rep, *msglen);
  351 
  352         return 0;
  353 }
  354 
  355 int
  356 mach_thread_get_state(args)
  357         struct mach_trap_args *args;
  358 {
  359         mach_thread_get_state_request_t *req = args->smsg;
  360         mach_thread_get_state_reply_t *rep = args->rmsg;
  361         size_t *msglen = args->rsize;
  362         struct lwp *tl = args->tl;
  363         int error;
  364         int size;
  365 
  366         /* Sanity check req->req_count */
  367         if (req->req_count > 144)
  368                 return mach_msg_error(args, EINVAL);
  369 
  370         if ((error = mach_thread_get_state_machdep(tl,
  371             req->req_flavor, &rep->rep_state, &size)) != 0)
  372                 return mach_msg_error(args, error);
  373 
  374         rep->rep_count = size / sizeof(int);
  375         *msglen = sizeof(*rep) + ((req->req_count - 144) * sizeof(int));
  376         mach_set_header(rep, req, *msglen);
  377         mach_set_trailer(rep, *msglen);
  378 
  379         return 0;
  380 }
  381 
  382 int
  383 mach_thread_set_state(args)
  384         struct mach_trap_args *args;
  385 {
  386         mach_thread_set_state_request_t *req = args->smsg;
  387         mach_thread_set_state_reply_t *rep = args->rmsg;
  388         size_t *msglen = args->rsize;
  389         struct lwp *tl = args->tl;
  390         int error;
  391         int end_offset;
  392 
  393         /* Sanity check req_count */
  394         end_offset = req->req_count;
  395         if (MACH_REQMSG_OVERFLOW(args, req->req_state[end_offset]))
  396                 return mach_msg_error(args, EINVAL);
  397 
  398         if ((error = mach_thread_set_state_machdep(tl,
  399             req->req_flavor, &req->req_state)) != 0)
  400                 return mach_msg_error(args, error);
  401 
  402         *msglen = sizeof(*rep);
  403         mach_set_header(rep, req, *msglen);
  404 
  405         rep->rep_retval = 0;
  406 
  407         mach_set_trailer(rep, *msglen);
  408 
  409         return 0;
  410 }
  411 
  412 int
  413 mach_thread_suspend(args)
  414         struct mach_trap_args *args;
  415 {
  416         mach_thread_suspend_request_t *req = args->smsg;
  417         mach_thread_suspend_reply_t *rep = args->rmsg;
  418         size_t *msglen = args->rsize;
  419         struct lwp *l = args->l;
  420         struct lwp *tl = args->tl;
  421         int error;
  422 
  423         error = lwp_suspend(l, tl);
  424 
  425         *msglen = sizeof(*rep);
  426         mach_set_header(rep, req, *msglen);
  427         rep->rep_retval = native_to_mach_errno[error];
  428         mach_set_trailer(rep, *msglen);
  429 
  430         return 0;
  431 }
  432 
  433 int
  434 mach_thread_resume(args)
  435         struct mach_trap_args *args;
  436 {
  437         mach_thread_resume_request_t *req = args->smsg;
  438         mach_thread_resume_reply_t *rep = args->rmsg;
  439         size_t *msglen = args->rsize;
  440         struct lwp *tl = args->tl;
  441 
  442         lwp_continue(tl);
  443 
  444         *msglen = sizeof(*rep);
  445         mach_set_header(rep, req, *msglen);
  446         rep->rep_retval = 0;
  447         mach_set_trailer(rep, *msglen);
  448 
  449         return 0;
  450 }
  451 
  452 int
  453 mach_thread_abort(args)
  454         struct mach_trap_args *args;
  455 {
  456         mach_thread_abort_request_t *req = args->smsg;
  457         mach_thread_abort_reply_t *rep = args->rmsg;
  458         size_t *msglen = args->rsize;
  459         struct lwp *tl = args->tl;
  460 
  461         lwp_exit(tl);
  462 
  463         *msglen = sizeof(*rep);
  464         mach_set_header(rep, req, *msglen);
  465         rep->rep_retval = 0;
  466         mach_set_trailer(rep, *msglen);
  467 
  468         return 0;
  469 }
  470 
  471 int
  472 mach_thread_set_policy(args)
  473         struct mach_trap_args *args;
  474 {
  475         mach_thread_set_policy_request_t *req = args->smsg;
  476         mach_thread_set_policy_reply_t *rep = args->rmsg;
  477         size_t *msglen = args->rsize;
  478         struct lwp *tl = args->tl;
  479         mach_port_t mn;
  480         struct mach_right *mr;
  481         int limit_count_offset, limit_offset;
  482         int limit_count;
  483         int *limit;
  484 
  485         limit_count_offset = req->req_base_count;
  486         if (MACH_REQMSG_OVERFLOW(args, req->req_base[limit_count_offset]))
  487                 return mach_msg_error(args, EINVAL);
  488 
  489         limit_count = req->req_base[limit_count_offset];
  490         limit_offset = limit_count_offset +
  491             (sizeof(req->req_limit_count) / sizeof(req->req_base[0]));
  492         limit = &req->req_base[limit_offset];
  493         if (MACH_REQMSG_OVERFLOW(args, limit[limit_count]))
  494                 return mach_msg_error(args, EINVAL);
  495 
  496         mn = req->req_pset.name;
  497         if ((mr = mach_right_check(mn, tl, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  498                 return mach_msg_error(args, EINVAL);
  499 
  500         *msglen = sizeof(*rep);
  501         mach_set_header(rep, req, *msglen);
  502         rep->rep_retval = 0;
  503         mach_set_trailer(rep, *msglen);
  504 
  505         return 0;
  506 }
  507 

Cache object: 902c0e716af64e41673ade03c0c4d2f4


[ 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.