int init_semaphores(){ char sem_name[100]; printf("Initializing semaphores...\n"); global_sem = sem_open(SIM_GLOBAL_SEM, 0); if(global_sem == SEM_FAILED){ printf("global_sem can not be created\n"); return -1; } /* Slurmctld and slurmd main threads are registered during initialization */ main_thread = pthread_self(); sem_wait(global_sem); main_thread = pthread_self(); main_thread_id = get_new_thread_id(&main_thread); threads_data[main_thread_id].sleep = -1; threads_data[main_thread_id].pid = getpid(); printf("Getting main_thread_id %d\n", main_thread_id); sem_post(global_sem); /* and then initializing semaphores for this main thread */ memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_PREFIX, main_thread_id); printf("Opening semaphore %s\n", sem_name); thread_sem[main_thread_id] = sem_open(sem_name, 0); if(thread_sem[main_thread_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", main_thread_id); return -1; } memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_BACK_PREFIX, main_thread_id); printf("Opening semaphore %s\n", sem_name); thread_sem_back[main_thread_id] = sem_open(sem_name, 0); if(thread_sem_back[main_thread_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", main_thread_id); return -1; } return 0; }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg){ int ret; char sem_name[100]; int s_id; int sval; int err = 0; int proto = 0; /* This wrapper executes the full code with global lock, even call to real pthread_create */ sem_wait(global_sem); pthread_create_counter[0]++; /* First of all, we need a simulation thread id. Under thread creation bursts could it be no * * free slot is available. This is what we call a proto-thread. It should be enough to wait * * some time till one slot is available. If the wait takes more than 10 seconds, something is * * wrong about the simulation */ while(1){ struct timespec waiting; s_id = get_new_thread_id(); if(s_id < 0){ if(proto == 0){ proto = 1; proto_threads[0]++; printf("WAITING FOR AN SLOT proto_threads: %d\n", proto_threads[0]); } sem_post(global_sem); } else break; err++; pthread_yield(); if(err == 1000){ printf("WARNING: pthread_create wrapper returning EAGAIN!!!\n"); proto_threads[0]--; return -EAGAIN; } waiting.tv_sec = 0; waiting.tv_nsec = 10000000; nanosleep(&waiting, 0); sem_wait(global_sem); } /* Once we got here the simulation thread is not a proto-thread any more */ if(proto) proto_threads[0]--; sim_lib_printf(0, "I GOT AN SLOT: proto_threads: %d\n", proto_threads[0]); /* simulation thread initialization */ /* Most of it is just for debugging except sleep field */ threads_data[s_id].sleep = -1; threads_data[s_id].creation = *current_sim; threads_data[s_id].deletion = 0; threads_data[s_id].last_sleep = 0; threads_data[s_id].never_ending = 0; threads_data[s_id].last_wakeup = 0; threads_data[s_id].wait_time = 0; threads_data[s_id].wait_count = 0; threads_data[s_id].func_addr = (unsigned long)start; threads_data[s_id].pid = getpid(); set_new_thread(s_id); /* Calling real pthread_create is needed at this point. We need pthread_id for linking * * a simulation thread id with a pthread_id. It could happen a fast thread trying to use * * this linking table before an entry has been created for it, but we are aware of this. * * The link is done as one of the last steps because we need to work for leaving all * * stable before the thread starts working with simulation structures. * */ ret = real_pthread_create(thread, attr, start, arg); /* Opening semaphores using simulation thread id */ memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_PREFIX, s_id); sim_lib_printf(0, "Opening semaphore %s\n", sem_name); thread_sem[s_id] = sem_open(sem_name, 0); if(thread_sem[s_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", s_id); return -1; } sem_getvalue(thread_sem[s_id], &sval); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_BACK_PREFIX, s_id); sim_lib_printf(0, "Opening semaphore %s\n", sem_name); thread_sem_back[s_id] = sem_open(sem_name, 0); if(thread_sem_back[s_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", s_id); return -1; } sem_getvalue(thread_sem_back[s_id], &sval); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); /* Sometimes previous thread using this semaphore left the wrong value */ while(sval > 1){ sem_wait(thread_sem_back[s_id]); sem_getvalue(thread_sem_back[s_id], &sval); } if(sval == 0) sem_post(thread_sem_back[s_id]); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); /* Is this really needed??? */ thread_info_list[s_id].id = s_id; sim_lib_printf(0, "Dentro de wrapper para pthread_create, getting sleep id %d [%lu]\n", thread_info_list[s_id].id , *(thread)); /* This is the important step. After this a thread can work with simulation wrappers */ thread_info_list[s_id].p = *thread; threads_data[s_id].is_new = 1; threads_data[s_id].ptid = *thread; sem_post(global_sem); return ret; }
void xloop(sock_t sock, sock_t ctl_sock) { fd_set sock_set; int retcode; pthread_attr_t pattr; int tid; sock_t conn; sigset_t curmask, oldmask; sock_t ctl_cli_sock = -1; /* prepare threads */ proxenet_xzero(threads, sizeof(pthread_t) * MAX_THREADS); if (pthread_attr_init(&pattr)) { xlog(LOG_ERROR, "%s\n", "Failed to pthread_attr_init"); return; } pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE); /* block useful signal */ sigemptyset(&curmask); sigaddset(&curmask, SIGTERM); sigaddset(&curmask, SIGINT); sigaddset(&curmask, SIGCHLD); if (pthread_sigmask(SIG_BLOCK, &curmask, &oldmask) < 0) { xlog(LOG_ERROR, "sigprocmask failed : %s\n", strerror(errno)); return; } /* proxenet is now running :) */ proxy_state = ACTIVE; /* big loop */ while (proxy_state != INACTIVE) { conn = -1; retcode = -1; FD_ZERO(&sock_set); FD_SET(sock, &sock_set); FD_SET(ctl_sock, &sock_set); if (ctl_cli_sock > 0) FD_SET(ctl_cli_sock, &sock_set); purge_zombies(); /* set asynchronous listener */ struct timespec timeout = { .tv_sec = 5, .tv_nsec = 0 }; retcode = pselect(FD_SETSIZE, &sock_set, NULL, NULL, &timeout, &oldmask); if (retcode < 0) { if (errno != EINTR) { xlog(LOG_ERROR, "[main] pselect() returned %d: %s\n", retcode, strerror(errno)); proxy_state = INACTIVE; break; } else { continue; } } if (retcode == 0) continue; if (proxy_state == INACTIVE) break; /* event on the listening socket -> new request */ if( FD_ISSET(sock, &sock_set) && proxy_state != SLEEPING) { #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "Incoming listening event"); #endif tid = get_new_thread_id(); if(tid < 0) { continue; } struct sockaddr addr; socklen_t addrlen = 0; proxenet_xzero(&addr, sizeof(struct sockaddr)); conn = accept(sock, &addr, &addrlen); if (conn < 0) { if(errno != EINTR) xlog(LOG_ERROR, "[main] accept() failed: %s\n", strerror(errno)); continue; } retcode = proxenet_start_new_thread(conn, tid, &threads[tid], &pattr); if (retcode < 0) { xlog(LOG_ERROR, "[main] %s\n", "Error while spawn new thread"); continue; } } /* end if _socket_event */ /* event on control listening socket */ if( FD_ISSET(ctl_sock, &sock_set) ) { #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "Incoming control event"); #endif struct sockaddr_un sun_cli; socklen_t sun_cli_len = 0; int new_conn = -1; proxenet_xzero(&sun_cli, sizeof(struct sockaddr_un)); new_conn = accept(ctl_sock, (struct sockaddr *)&sun_cli, &sun_cli_len); if (new_conn < 0) { xlog(LOG_ERROR, "[main] control accept() failed: %s\n", strerror(errno)); continue; } if (ctl_cli_sock < 0) { ctl_cli_sock = new_conn; xlog(LOG_INFO, "%s\n", "New connection on Control socket"); proxenet_write(ctl_cli_sock, CONTROL_MOTD, strlen(CONTROL_MOTD)); proxenet_write(ctl_cli_sock, CONTROL_PROMPT, strlen(CONTROL_PROMPT)); } else { if(new_conn > 0) { xlog(LOG_ERROR, "%s\n", "Denied control connection: already established"); if(close_socket(new_conn) < 0) { xlog(LOG_ERROR, "Failed to close socket: %s\n", strerror(errno)); } } } }/* end if _control_listening_event */ /* event on control socket */ if( ctl_cli_sock > 0 && FD_ISSET(ctl_cli_sock, &sock_set) ) { if (proxenet_handle_control_event(&ctl_cli_sock) < 0) { close_socket(ctl_cli_sock); ctl_cli_sock = -1; } } /* end if _control_event */ } /* endof while(!INACTIVE) */ kill_zombies(); proxenet_destroy_plugins_vm(); pthread_attr_destroy(&pattr); return; } /** * * @param signum */ void sighandler(int signum) { #ifdef DEBUG xlog(LOG_DEBUG, "Received signal %s [%d]\n", strsignal(signum), signum); #endif switch(signum) { case SIGTERM: case SIGINT: if (proxy_state != INACTIVE) proxy_state = INACTIVE; cfg->try_exit++; xlog(LOG_INFO, "%s, %d/%d\n", "Trying to leave", cfg->try_exit, cfg->try_exit_max); if (cfg->try_exit == cfg->try_exit_max) { xlog(LOG_CRITICAL, "%s\n", "Failed to exit properly"); abort(); } break; case SIGCHLD: purge_zombies(); break; } }