Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  25  */
  26 
  27 /*
  28  * restarter.c - service manipulation
  29  *
  30  * This component manages services whose restarter is svc.startd, the standard
  31  * restarter.  It translates restarter protocol events from the graph engine
  32  * into actions on processes, as a delegated restarter would do.
  33  *
  34  * The master restarter manages a number of always-running threads:
  35  *   - restarter event thread: events from the graph engine
  36  *   - timeout thread: thread to fire queued timeouts
  37  *   - contract thread: thread to handle contract events
  38  *   - wait thread: thread to handle wait-based services
  39  *
  40  * The other threads are created as-needed:
  41  *   - per-instance method threads
  42  *   - per-instance event processing threads
  43  *
  44  * The interaction of all threads must result in the following conditions


 977 
 978                         case EACCES:
 979                         default:
 980                                 bad_error("libscf_snapshots_poststart", r);
 981                         }
 982                 }
 983 
 984                 MUTEX_UNLOCK(&inst->ri_lock);
 985         }
 986 
 987         MUTEX_UNLOCK(&instance_list.ril_lock);
 988 }
 989 
 990 /* ARGSUSED */
 991 void *
 992 restarter_post_fsminimal_thread(void *unused)
 993 {
 994         scf_handle_t *h;
 995         int r;
 996 


 997         h = libscf_handle_create_bound_loop();
 998 
 999         for (;;) {
1000                 r = libscf_create_self(h);
1001                 if (r == 0)
1002                         break;
1003 
1004                 assert(r == ECONNABORTED);
1005                 libscf_handle_rebind(h);
1006         }
1007 
1008         restarter_take_pending_snapshots(h);
1009 
1010         (void) scf_handle_unbind(h);
1011         scf_handle_destroy(h);
1012 
1013         return (NULL);
1014 }
1015 
1016 /*


1754         "INVALID_DEPENDENCY", "ADMIN_DISABLE", "STOP_RESET"
1755 };
1756 
1757 /*
1758  * void *restarter_process_events()
1759  *
1760  *   Called in a separate thread to process the events on an instance's
1761  *   queue.  Empties the queue completely, and tries to keep the thread
1762  *   around for a little while after the queue is empty to save on
1763  *   startup costs.
1764  */
1765 static void *
1766 restarter_process_events(void *arg)
1767 {
1768         scf_handle_t *h;
1769         restarter_instance_qentry_t *event;
1770         restarter_inst_t *rip;
1771         char *fmri = (char *)arg;
1772         struct timespec to;
1773 


1774         assert(fmri != NULL);
1775 
1776         h = libscf_handle_create_bound_loop();
1777 
1778         /* grab the queue lock */
1779         rip = inst_lookup_queue(fmri);
1780         if (rip == NULL)
1781                 goto out;
1782 
1783 again:
1784 
1785         while ((event = uu_list_first(rip->ri_queue)) != NULL) {
1786                 restarter_inst_t *inst;
1787 
1788                 /* drop the queue lock */
1789                 MUTEX_UNLOCK(&rip->ri_queue_lock);
1790 
1791                 /*
1792                  * Grab the inst lock -- this waits until any outstanding
1793                  * method finishes running.


1922          */
1923         to.tv_sec = 3;
1924         to.tv_nsec = 0;
1925         (void) pthread_cond_reltimedwait_np(&rip->ri_queue_cv,
1926             &rip->ri_queue_lock, &to);
1927 
1928         if (uu_list_first(rip->ri_queue) != NULL)
1929                 goto again;
1930 
1931         rip->ri_queue_thread = 0;
1932         MUTEX_UNLOCK(&rip->ri_queue_lock);
1933 
1934 out:
1935         (void) scf_handle_unbind(h);
1936         scf_handle_destroy(h);
1937         free(fmri);
1938         return (NULL);
1939 }
1940 
1941 static int
1942 is_admin_event(restarter_event_type_t t) {
1943 
1944         switch (t) {
1945         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1946         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE:
1947         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
1948         case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
1949         case RESTARTER_EVENT_TYPE_ADMIN_DEGRADED:
1950         case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
1951                 return (1);
1952         default:
1953                 return (0);
1954         }
1955 }
1956 
1957 static void
1958 restarter_queue_event(restarter_inst_t *ri, restarter_protocol_event_t *e)
1959 {
1960         restarter_instance_qentry_t *qe;
1961         int r;
1962 
1963         assert(MUTEX_HELD(&ri->ri_queue_lock));


1968         qe->riq_reason = e->rpe_reason;
1969 
1970         uu_list_node_init(qe, &qe->riq_link, restarter_queue_pool);
1971         r = uu_list_insert_before(ri->ri_queue, NULL, qe);
1972         assert(r == 0);
1973 }
1974 
1975 /*
1976  * void *restarter_event_thread()
1977  *
1978  *  Handle incoming graph events by placing them on a per-instance
1979  *  queue.  We can't lock the main part of the instance structure, so
1980  *  just modify the seprarately locked event queue portion.
1981  */
1982 /*ARGSUSED*/
1983 static void *
1984 restarter_event_thread(void *unused)
1985 {
1986         scf_handle_t *h;
1987 


1988         /*
1989          * This is a new thread, and thus, gets its own handle
1990          * to the repository.
1991          */
1992         h = libscf_handle_create_bound_loop();
1993 
1994         MUTEX_LOCK(&ru->restarter_update_lock);
1995 
1996         /*CONSTCOND*/
1997         while (1) {
1998                 restarter_protocol_event_t *e;
1999 
2000                 while (ru->restarter_update_wakeup == 0)
2001                         (void) pthread_cond_wait(&ru->restarter_update_cv,
2002                             &ru->restarter_update_lock);
2003 
2004                 ru->restarter_update_wakeup = 0;
2005 
2006                 while ((e = restarter_event_dequeue()) != NULL) {
2007                         restarter_inst_t *rip;


2179                         break;
2180                 case CT_PR_EV_HWERR:
2181                         (void) stop_instance(h, inst, RSTOP_HWERR);
2182                         break;
2183                 }
2184         }
2185 }
2186 
2187 /*
2188  * void *restarter_contract_event_thread(void *)
2189  *   Listens to the process contract bundle for critical events, taking action
2190  *   on events from contracts we know we are responsible for.
2191  */
2192 /*ARGSUSED*/
2193 static void *
2194 restarter_contracts_event_thread(void *unused)
2195 {
2196         int fd, err;
2197         scf_handle_t *local_handle;
2198 


2199         /*
2200          * Await graph load completion.  That is, stop here, until we've scanned
2201          * the repository for contract - instance associations.
2202          */
2203         MUTEX_LOCK(&st->st_load_lock);
2204         while (!(st->st_load_complete && st->st_load_instances == 0))
2205                 (void) pthread_cond_wait(&st->st_load_cv, &st->st_load_lock);
2206         MUTEX_UNLOCK(&st->st_load_lock);
2207 
2208         /*
2209          * This is a new thread, and thus, gets its own handle
2210          * to the repository.
2211          */
2212         if ((local_handle = libscf_handle_create_bound(SCF_VERSION)) == NULL)
2213                 uu_die("Unable to bind a new repository handle: %s\n",
2214                     scf_strerror(scf_error()));
2215 
2216         fd = open64(CTFS_ROOT "/process/pbundle", O_RDONLY);
2217         if (fd == -1)
2218                 uu_die("process bundle open failed");


2528 
2529         return (ret);
2530 }
2531 
2532 /*
2533  * void *restarter_timeouts_event_thread(void *)
2534  *   Responsible for monitoring the method timeouts.  This thread must
2535  *   be started before any methods are called.
2536  */
2537 /*ARGSUSED*/
2538 static void *
2539 restarter_timeouts_event_thread(void *unused)
2540 {
2541         /*
2542          * Timeouts are entered on a priority queue, which is processed by
2543          * this thread.  As timeouts are specified in seconds, we'll do
2544          * the necessary processing every second, as long as the queue
2545          * is not empty.
2546          */
2547 


2548         /*CONSTCOND*/
2549         while (1) {
2550                 /*
2551                  * As long as the timeout list isn't empty, process it
2552                  * every second.
2553                  */
2554                 if (timeout_now() == 0) {
2555                         (void) sleep(1);
2556                         continue;
2557                 }
2558 
2559                 /* The list is empty, wait until we have more timeouts. */
2560                 MUTEX_LOCK(&tu->tu_lock);
2561 
2562                 while (tu->tu_wakeup == 0)
2563                         (void) pthread_cond_wait(&tu->tu_cv, &tu->tu_lock);
2564 
2565                 tu->tu_wakeup = 0;
2566                 MUTEX_UNLOCK(&tu->tu_lock);
2567         }




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Joyent, Inc.
  25  */
  26 
  27 /*
  28  * restarter.c - service manipulation
  29  *
  30  * This component manages services whose restarter is svc.startd, the standard
  31  * restarter.  It translates restarter protocol events from the graph engine
  32  * into actions on processes, as a delegated restarter would do.
  33  *
  34  * The master restarter manages a number of always-running threads:
  35  *   - restarter event thread: events from the graph engine
  36  *   - timeout thread: thread to fire queued timeouts
  37  *   - contract thread: thread to handle contract events
  38  *   - wait thread: thread to handle wait-based services
  39  *
  40  * The other threads are created as-needed:
  41  *   - per-instance method threads
  42  *   - per-instance event processing threads
  43  *
  44  * The interaction of all threads must result in the following conditions


 977 
 978                         case EACCES:
 979                         default:
 980                                 bad_error("libscf_snapshots_poststart", r);
 981                         }
 982                 }
 983 
 984                 MUTEX_UNLOCK(&inst->ri_lock);
 985         }
 986 
 987         MUTEX_UNLOCK(&instance_list.ril_lock);
 988 }
 989 
 990 /* ARGSUSED */
 991 void *
 992 restarter_post_fsminimal_thread(void *unused)
 993 {
 994         scf_handle_t *h;
 995         int r;
 996 
 997         (void) pthread_setname_np(pthread_self(), "restarter_post_fsmin");
 998 
 999         h = libscf_handle_create_bound_loop();
1000 
1001         for (;;) {
1002                 r = libscf_create_self(h);
1003                 if (r == 0)
1004                         break;
1005 
1006                 assert(r == ECONNABORTED);
1007                 libscf_handle_rebind(h);
1008         }
1009 
1010         restarter_take_pending_snapshots(h);
1011 
1012         (void) scf_handle_unbind(h);
1013         scf_handle_destroy(h);
1014 
1015         return (NULL);
1016 }
1017 
1018 /*


1756         "INVALID_DEPENDENCY", "ADMIN_DISABLE", "STOP_RESET"
1757 };
1758 
1759 /*
1760  * void *restarter_process_events()
1761  *
1762  *   Called in a separate thread to process the events on an instance's
1763  *   queue.  Empties the queue completely, and tries to keep the thread
1764  *   around for a little while after the queue is empty to save on
1765  *   startup costs.
1766  */
1767 static void *
1768 restarter_process_events(void *arg)
1769 {
1770         scf_handle_t *h;
1771         restarter_instance_qentry_t *event;
1772         restarter_inst_t *rip;
1773         char *fmri = (char *)arg;
1774         struct timespec to;
1775 
1776         (void) pthread_setname_np(pthread_self(), "restarter_process_events");
1777 
1778         assert(fmri != NULL);
1779 
1780         h = libscf_handle_create_bound_loop();
1781 
1782         /* grab the queue lock */
1783         rip = inst_lookup_queue(fmri);
1784         if (rip == NULL)
1785                 goto out;
1786 
1787 again:
1788 
1789         while ((event = uu_list_first(rip->ri_queue)) != NULL) {
1790                 restarter_inst_t *inst;
1791 
1792                 /* drop the queue lock */
1793                 MUTEX_UNLOCK(&rip->ri_queue_lock);
1794 
1795                 /*
1796                  * Grab the inst lock -- this waits until any outstanding
1797                  * method finishes running.


1926          */
1927         to.tv_sec = 3;
1928         to.tv_nsec = 0;
1929         (void) pthread_cond_reltimedwait_np(&rip->ri_queue_cv,
1930             &rip->ri_queue_lock, &to);
1931 
1932         if (uu_list_first(rip->ri_queue) != NULL)
1933                 goto again;
1934 
1935         rip->ri_queue_thread = 0;
1936         MUTEX_UNLOCK(&rip->ri_queue_lock);
1937 
1938 out:
1939         (void) scf_handle_unbind(h);
1940         scf_handle_destroy(h);
1941         free(fmri);
1942         return (NULL);
1943 }
1944 
1945 static int
1946 is_admin_event(restarter_event_type_t t)
1947 {
1948         switch (t) {
1949         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1950         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON_IMMEDIATE:
1951         case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
1952         case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
1953         case RESTARTER_EVENT_TYPE_ADMIN_DEGRADED:
1954         case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
1955                 return (1);
1956         default:
1957                 return (0);
1958         }
1959 }
1960 
1961 static void
1962 restarter_queue_event(restarter_inst_t *ri, restarter_protocol_event_t *e)
1963 {
1964         restarter_instance_qentry_t *qe;
1965         int r;
1966 
1967         assert(MUTEX_HELD(&ri->ri_queue_lock));


1972         qe->riq_reason = e->rpe_reason;
1973 
1974         uu_list_node_init(qe, &qe->riq_link, restarter_queue_pool);
1975         r = uu_list_insert_before(ri->ri_queue, NULL, qe);
1976         assert(r == 0);
1977 }
1978 
1979 /*
1980  * void *restarter_event_thread()
1981  *
1982  *  Handle incoming graph events by placing them on a per-instance
1983  *  queue.  We can't lock the main part of the instance structure, so
1984  *  just modify the seprarately locked event queue portion.
1985  */
1986 /*ARGSUSED*/
1987 static void *
1988 restarter_event_thread(void *unused)
1989 {
1990         scf_handle_t *h;
1991 
1992         (void) pthread_setname_np(pthread_self(), "restarter_event");
1993 
1994         /*
1995          * This is a new thread, and thus, gets its own handle
1996          * to the repository.
1997          */
1998         h = libscf_handle_create_bound_loop();
1999 
2000         MUTEX_LOCK(&ru->restarter_update_lock);
2001 
2002         /*CONSTCOND*/
2003         while (1) {
2004                 restarter_protocol_event_t *e;
2005 
2006                 while (ru->restarter_update_wakeup == 0)
2007                         (void) pthread_cond_wait(&ru->restarter_update_cv,
2008                             &ru->restarter_update_lock);
2009 
2010                 ru->restarter_update_wakeup = 0;
2011 
2012                 while ((e = restarter_event_dequeue()) != NULL) {
2013                         restarter_inst_t *rip;


2185                         break;
2186                 case CT_PR_EV_HWERR:
2187                         (void) stop_instance(h, inst, RSTOP_HWERR);
2188                         break;
2189                 }
2190         }
2191 }
2192 
2193 /*
2194  * void *restarter_contract_event_thread(void *)
2195  *   Listens to the process contract bundle for critical events, taking action
2196  *   on events from contracts we know we are responsible for.
2197  */
2198 /*ARGSUSED*/
2199 static void *
2200 restarter_contracts_event_thread(void *unused)
2201 {
2202         int fd, err;
2203         scf_handle_t *local_handle;
2204 
2205         (void) pthread_setname_np(pthread_self(), "restarter_contracts_event");
2206 
2207         /*
2208          * Await graph load completion.  That is, stop here, until we've scanned
2209          * the repository for contract - instance associations.
2210          */
2211         MUTEX_LOCK(&st->st_load_lock);
2212         while (!(st->st_load_complete && st->st_load_instances == 0))
2213                 (void) pthread_cond_wait(&st->st_load_cv, &st->st_load_lock);
2214         MUTEX_UNLOCK(&st->st_load_lock);
2215 
2216         /*
2217          * This is a new thread, and thus, gets its own handle
2218          * to the repository.
2219          */
2220         if ((local_handle = libscf_handle_create_bound(SCF_VERSION)) == NULL)
2221                 uu_die("Unable to bind a new repository handle: %s\n",
2222                     scf_strerror(scf_error()));
2223 
2224         fd = open64(CTFS_ROOT "/process/pbundle", O_RDONLY);
2225         if (fd == -1)
2226                 uu_die("process bundle open failed");


2536 
2537         return (ret);
2538 }
2539 
2540 /*
2541  * void *restarter_timeouts_event_thread(void *)
2542  *   Responsible for monitoring the method timeouts.  This thread must
2543  *   be started before any methods are called.
2544  */
2545 /*ARGSUSED*/
2546 static void *
2547 restarter_timeouts_event_thread(void *unused)
2548 {
2549         /*
2550          * Timeouts are entered on a priority queue, which is processed by
2551          * this thread.  As timeouts are specified in seconds, we'll do
2552          * the necessary processing every second, as long as the queue
2553          * is not empty.
2554          */
2555 
2556         (void) pthread_setname_np(pthread_self(), "restarter_timeouts_event");
2557 
2558         /*CONSTCOND*/
2559         while (1) {
2560                 /*
2561                  * As long as the timeout list isn't empty, process it
2562                  * every second.
2563                  */
2564                 if (timeout_now() == 0) {
2565                         (void) sleep(1);
2566                         continue;
2567                 }
2568 
2569                 /* The list is empty, wait until we have more timeouts. */
2570                 MUTEX_LOCK(&tu->tu_lock);
2571 
2572                 while (tu->tu_wakeup == 0)
2573                         (void) pthread_cond_wait(&tu->tu_cv, &tu->tu_lock);
2574 
2575                 tu->tu_wakeup = 0;
2576                 MUTEX_UNLOCK(&tu->tu_lock);
2577         }