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) 2015, Syneto S.R.L. All rights reserved.
  25  * Copyright 2016 Toomas Soome <tsoome@me.com>
  26  * Copyright 2016 RackTop Systems.
  27  */
  28 
  29 /*
  30  * graph.c - master restarter graph engine
  31  *
  32  *   The graph engine keeps a dependency graph of all service instances on the
  33  *   system, as recorded in the repository.  It decides when services should
  34  *   be brought up or down based on service states and dependencies and sends
  35  *   commands to restarters to effect any changes.  It also executes
  36  *   administrator commands sent by svcadm via the repository.
  37  *
  38  *   The graph is stored in uu_list_t *dgraph and its vertices are
  39  *   graph_vertex_t's, each of which has a name and an integer id unique to
  40  *   its name (see dict.c).  A vertex's type attribute designates the type
  41  *   of object it represents: GVT_INST for service instances, GVT_SVC for
  42  *   service objects (since service instances may depend on another service,
  43  *   rather than service instance), GVT_FILE for files (which services may


3832                                 vertex_send_event(v,
3833                                     RESTARTER_EVENT_TYPE_START);
3834                         else
3835                                 v->gv_start_f(v);
3836                 }
3837 
3838                 console_login_ready = B_FALSE;
3839         }
3840 
3841         return (0);
3842 }
3843 
3844 /*
3845  * The sulogin thread runs sulogin while can_come_up() is false.  run_sulogin()
3846  * keeps sulogin from stepping on console-login's toes.
3847  */
3848 /* ARGSUSED */
3849 static void *
3850 sulogin_thread(void *unused)
3851 {


3852         MUTEX_LOCK(&dgraph_lock);
3853 
3854         assert(sulogin_thread_running);
3855 
3856         do {
3857                 (void) run_sulogin("Console login service(s) cannot run\n");
3858         } while (!can_come_up());
3859 
3860         sulogin_thread_running = B_FALSE;
3861         MUTEX_UNLOCK(&dgraph_lock);
3862 
3863         return (NULL);
3864 }
3865 
3866 /* ARGSUSED */
3867 void *
3868 single_user_thread(void *unused)
3869 {
3870         uint_t left;
3871         scf_handle_t *h;
3872         scf_instance_t *inst;
3873         scf_property_t *prop;
3874         scf_value_t *val;
3875         const char *msg;
3876         char *buf;
3877         int r;
3878 


3879         MUTEX_LOCK(&single_user_thread_lock);
3880         single_user_thread_count++;
3881 
3882         if (!booting_to_single_user)
3883                 kill_user_procs();
3884 
3885         if (go_single_user_mode || booting_to_single_user) {
3886                 msg = "SINGLE USER MODE\n";
3887         } else {
3888                 assert(go_to_level1);
3889 
3890                 fork_rc_script('1', "start", B_TRUE);
3891 
3892                 uu_warn("The system is ready for administration.\n");
3893 
3894                 msg = "";
3895         }
3896 
3897         MUTEX_UNLOCK(&single_user_thread_lock);
3898 


5762                 log_error(LOG_WARNING,
5763                     "graph_event_loop received an unknown event: %d\n",
5764                     e->gpe_type);
5765                 break;
5766         }
5767 
5768         return (0);
5769 }
5770 
5771 /*
5772  * graph_event_thread()
5773  *    Wait for state changes from the restarters.
5774  */
5775 /*ARGSUSED*/
5776 void *
5777 graph_event_thread(void *unused)
5778 {
5779         scf_handle_t *h;
5780         int err;
5781 


5782         h = libscf_handle_create_bound_loop();
5783 
5784         /*CONSTCOND*/
5785         while (1) {
5786                 graph_protocol_event_t *e;
5787 
5788                 MUTEX_LOCK(&gu->gu_lock);
5789 
5790                 while (gu->gu_wakeup == 0)
5791                         (void) pthread_cond_wait(&gu->gu_cv, &gu->gu_lock);
5792 
5793                 gu->gu_wakeup = 0;
5794 
5795                 while ((e = graph_event_dequeue()) != NULL) {
5796                         MUTEX_LOCK(&e->gpe_lock);
5797                         MUTEX_UNLOCK(&gu->gu_lock);
5798 
5799                         while ((err = handle_graph_update_event(h, e)) ==
5800                             ECONNABORTED)
5801                                 libscf_handle_rebind(h);


6121 
6122 out:
6123         startd_free(fmri, max_scf_fmri_size);
6124         scf_value_destroy(val);
6125         scf_property_destroy(prop);
6126         scf_instance_destroy(inst);
6127 }
6128 
6129 /*
6130  * void *graph_thread(void *)
6131  *
6132  * Graph management thread.
6133  */
6134 /*ARGSUSED*/
6135 void *
6136 graph_thread(void *arg)
6137 {
6138         scf_handle_t *h;
6139         int err;
6140 


6141         h = libscf_handle_create_bound_loop();
6142 
6143         if (st->st_initial)
6144                 set_initial_milestone(h);
6145 
6146         MUTEX_LOCK(&dgraph_lock);
6147         initial_milestone_set = B_TRUE;
6148         err = pthread_cond_broadcast(&initial_milestone_cv);
6149         assert(err == 0);
6150         MUTEX_UNLOCK(&dgraph_lock);
6151 
6152         libscf_populate_graph(h);
6153 
6154         if (!st->st_initial)
6155                 set_restart_milestone(h);
6156 
6157         MUTEX_LOCK(&st->st_load_lock);
6158         st->st_load_complete = 1;
6159         (void) pthread_cond_broadcast(&st->st_load_cv);
6160         MUTEX_UNLOCK(&st->st_load_lock);


6777 
6778                 end_inst_fmri[0] = '\0';
6779 
6780                 (void) dgraph_remove_instance(fmri, h);
6781         }
6782 
6783         free(lfmri);
6784 }
6785 
6786 /*ARGSUSED*/
6787 void *
6788 repository_event_thread(void *unused)
6789 {
6790         scf_handle_t *h;
6791         scf_propertygroup_t *pg;
6792         scf_instance_t *inst;
6793         char *fmri = startd_alloc(max_scf_fmri_size);
6794         char *pg_name = startd_alloc(max_scf_value_size);
6795         int r;
6796 


6797         h = libscf_handle_create_bound_loop();
6798 
6799         pg = safe_scf_pg_create(h);
6800         inst = safe_scf_instance_create(h);
6801 
6802 retry:
6803         if (_scf_notify_add_pgtype(h, SCF_GROUP_FRAMEWORK) != SCF_SUCCESS) {
6804                 if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) {
6805                         libscf_handle_rebind(h);
6806                 } else {
6807                         log_error(LOG_WARNING,
6808                             "Couldn't set up repository notification "
6809                             "for property group type %s: %s\n",
6810                             SCF_GROUP_FRAMEWORK, scf_strerror(scf_error()));
6811 
6812                         (void) sleep(1);
6813                 }
6814 
6815                 goto retry;
6816         }




   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  * Copyright (c) 2015, Syneto S.R.L. All rights reserved.
  26  * Copyright 2016 Toomas Soome <tsoome@me.com>
  27  * Copyright 2016 RackTop Systems.
  28  */
  29 
  30 /*
  31  * graph.c - master restarter graph engine
  32  *
  33  *   The graph engine keeps a dependency graph of all service instances on the
  34  *   system, as recorded in the repository.  It decides when services should
  35  *   be brought up or down based on service states and dependencies and sends
  36  *   commands to restarters to effect any changes.  It also executes
  37  *   administrator commands sent by svcadm via the repository.
  38  *
  39  *   The graph is stored in uu_list_t *dgraph and its vertices are
  40  *   graph_vertex_t's, each of which has a name and an integer id unique to
  41  *   its name (see dict.c).  A vertex's type attribute designates the type
  42  *   of object it represents: GVT_INST for service instances, GVT_SVC for
  43  *   service objects (since service instances may depend on another service,
  44  *   rather than service instance), GVT_FILE for files (which services may


3833                                 vertex_send_event(v,
3834                                     RESTARTER_EVENT_TYPE_START);
3835                         else
3836                                 v->gv_start_f(v);
3837                 }
3838 
3839                 console_login_ready = B_FALSE;
3840         }
3841 
3842         return (0);
3843 }
3844 
3845 /*
3846  * The sulogin thread runs sulogin while can_come_up() is false.  run_sulogin()
3847  * keeps sulogin from stepping on console-login's toes.
3848  */
3849 /* ARGSUSED */
3850 static void *
3851 sulogin_thread(void *unused)
3852 {
3853         (void) pthread_setname_np(pthread_self(), "sulogin");
3854 
3855         MUTEX_LOCK(&dgraph_lock);
3856 
3857         assert(sulogin_thread_running);
3858 
3859         do {
3860                 (void) run_sulogin("Console login service(s) cannot run\n");
3861         } while (!can_come_up());
3862 
3863         sulogin_thread_running = B_FALSE;
3864         MUTEX_UNLOCK(&dgraph_lock);
3865 
3866         return (NULL);
3867 }
3868 
3869 /* ARGSUSED */
3870 void *
3871 single_user_thread(void *unused)
3872 {
3873         uint_t left;
3874         scf_handle_t *h;
3875         scf_instance_t *inst;
3876         scf_property_t *prop;
3877         scf_value_t *val;
3878         const char *msg;
3879         char *buf;
3880         int r;
3881 
3882         (void) pthread_setname_np(pthread_self(), "single_user");
3883 
3884         MUTEX_LOCK(&single_user_thread_lock);
3885         single_user_thread_count++;
3886 
3887         if (!booting_to_single_user)
3888                 kill_user_procs();
3889 
3890         if (go_single_user_mode || booting_to_single_user) {
3891                 msg = "SINGLE USER MODE\n";
3892         } else {
3893                 assert(go_to_level1);
3894 
3895                 fork_rc_script('1', "start", B_TRUE);
3896 
3897                 uu_warn("The system is ready for administration.\n");
3898 
3899                 msg = "";
3900         }
3901 
3902         MUTEX_UNLOCK(&single_user_thread_lock);
3903 


5767                 log_error(LOG_WARNING,
5768                     "graph_event_loop received an unknown event: %d\n",
5769                     e->gpe_type);
5770                 break;
5771         }
5772 
5773         return (0);
5774 }
5775 
5776 /*
5777  * graph_event_thread()
5778  *    Wait for state changes from the restarters.
5779  */
5780 /*ARGSUSED*/
5781 void *
5782 graph_event_thread(void *unused)
5783 {
5784         scf_handle_t *h;
5785         int err;
5786 
5787         (void) pthread_setname_np(pthread_self(), "graph_event");
5788 
5789         h = libscf_handle_create_bound_loop();
5790 
5791         /*CONSTCOND*/
5792         while (1) {
5793                 graph_protocol_event_t *e;
5794 
5795                 MUTEX_LOCK(&gu->gu_lock);
5796 
5797                 while (gu->gu_wakeup == 0)
5798                         (void) pthread_cond_wait(&gu->gu_cv, &gu->gu_lock);
5799 
5800                 gu->gu_wakeup = 0;
5801 
5802                 while ((e = graph_event_dequeue()) != NULL) {
5803                         MUTEX_LOCK(&e->gpe_lock);
5804                         MUTEX_UNLOCK(&gu->gu_lock);
5805 
5806                         while ((err = handle_graph_update_event(h, e)) ==
5807                             ECONNABORTED)
5808                                 libscf_handle_rebind(h);


6128 
6129 out:
6130         startd_free(fmri, max_scf_fmri_size);
6131         scf_value_destroy(val);
6132         scf_property_destroy(prop);
6133         scf_instance_destroy(inst);
6134 }
6135 
6136 /*
6137  * void *graph_thread(void *)
6138  *
6139  * Graph management thread.
6140  */
6141 /*ARGSUSED*/
6142 void *
6143 graph_thread(void *arg)
6144 {
6145         scf_handle_t *h;
6146         int err;
6147 
6148         (void) pthread_setname_np(pthread_self(), "graph");
6149 
6150         h = libscf_handle_create_bound_loop();
6151 
6152         if (st->st_initial)
6153                 set_initial_milestone(h);
6154 
6155         MUTEX_LOCK(&dgraph_lock);
6156         initial_milestone_set = B_TRUE;
6157         err = pthread_cond_broadcast(&initial_milestone_cv);
6158         assert(err == 0);
6159         MUTEX_UNLOCK(&dgraph_lock);
6160 
6161         libscf_populate_graph(h);
6162 
6163         if (!st->st_initial)
6164                 set_restart_milestone(h);
6165 
6166         MUTEX_LOCK(&st->st_load_lock);
6167         st->st_load_complete = 1;
6168         (void) pthread_cond_broadcast(&st->st_load_cv);
6169         MUTEX_UNLOCK(&st->st_load_lock);


6786 
6787                 end_inst_fmri[0] = '\0';
6788 
6789                 (void) dgraph_remove_instance(fmri, h);
6790         }
6791 
6792         free(lfmri);
6793 }
6794 
6795 /*ARGSUSED*/
6796 void *
6797 repository_event_thread(void *unused)
6798 {
6799         scf_handle_t *h;
6800         scf_propertygroup_t *pg;
6801         scf_instance_t *inst;
6802         char *fmri = startd_alloc(max_scf_fmri_size);
6803         char *pg_name = startd_alloc(max_scf_value_size);
6804         int r;
6805 
6806         (void) pthread_setname_np(pthread_self(), "repository_event");
6807 
6808         h = libscf_handle_create_bound_loop();
6809 
6810         pg = safe_scf_pg_create(h);
6811         inst = safe_scf_instance_create(h);
6812 
6813 retry:
6814         if (_scf_notify_add_pgtype(h, SCF_GROUP_FRAMEWORK) != SCF_SUCCESS) {
6815                 if (scf_error() == SCF_ERROR_CONNECTION_BROKEN) {
6816                         libscf_handle_rebind(h);
6817                 } else {
6818                         log_error(LOG_WARNING,
6819                             "Couldn't set up repository notification "
6820                             "for property group type %s: %s\n",
6821                             SCF_GROUP_FRAMEWORK, scf_strerror(scf_error()));
6822 
6823                         (void) sleep(1);
6824                 }
6825 
6826                 goto retry;
6827         }