Plugin: Add STAGE_10 Loader
[MonkeyD.git] / src / scheduler.c
blob44b8be04e29b59a0f68fbd46ce9ad616b95f86a7
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2008, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <pthread.h>
26 #include <sys/epoll.h>
27 #include <unistd.h>
28 #include <sys/syscall.h>
29 #include <string.h>
31 #include "monkey.h"
32 #include "conn_switch.h"
33 #include "signal.h"
34 #include "scheduler.h"
35 #include "memory.h"
36 #include "epoll.h"
37 #include "request.h"
38 #include "cache.h"
39 #include "config.h"
41 /* Register thread information */
42 int mk_sched_register_thread(pthread_t tid, int efd)
44 struct sched_list_node *sr, *aux;
46 sr = mk_mem_malloc_z(sizeof(struct sched_list_node));
47 sr->tid = tid;
48 sr->pid = -1;
49 sr->epoll_fd = efd;
50 sr->request_handler = NULL;
51 sr->next = NULL;
53 if(!sched_list)
55 sr->idx = 1;
56 sched_list = sr;
57 return 0;
60 aux = sched_list;
61 while(aux->next)
63 aux = aux->next;
65 sr->idx = aux->idx + 1;
66 aux->next = sr;
68 return 0;
72 * Create thread which will be listening
73 * for incomings file descriptors
75 int mk_sched_launch_thread(int max_events)
77 int efd;
78 pthread_t tid;
79 pthread_attr_t attr;
80 sched_thread_conf *thconf;
81 pthread_mutex_t mutex_wait_register;
83 /* Creating epoll file descriptor */
84 efd = mk_epoll_create(max_events);
85 if(efd < 1)
87 return -1;
90 /* Thread stuff */
91 pthread_mutex_init(&mutex_wait_register,(pthread_mutexattr_t *) NULL);
92 pthread_mutex_lock(&mutex_wait_register);
94 thconf = mk_mem_malloc(sizeof(sched_thread_conf));
95 thconf->epoll_fd = efd;
96 thconf->max_events = max_events;
98 pthread_attr_init(&attr);
99 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
100 if(pthread_create(&tid, &attr, mk_sched_launch_epoll_loop,
101 (void *) thconf)!=0)
103 perror("pthread_create");
104 return -1;
107 /* Register working thread */
108 mk_sched_register_thread(tid, efd);
109 pthread_mutex_unlock(&mutex_wait_register);
110 return 0;
113 /* created thread, all this calls are in the thread context */
114 void *mk_sched_launch_epoll_loop(void *thread_conf)
116 sched_thread_conf *thconf;
117 struct sched_list_node *thinfo;
119 /* Avoid SIGPIPE signals */
120 mk_signal_thread_sigpipe_safe();
122 thconf = thread_conf;
124 /* Init specific thread cache */
125 mk_cache_thread_init();
127 mk_epoll_calls *callers;
128 callers = mk_epoll_set_callers((void *)mk_conn_switch,
129 MK_CONN_SWITCH_READ,
130 MK_CONN_SWITCH_WRITE);
132 /* Nasty way to export task id */
133 usleep(1000);
134 thinfo = mk_sched_get_thread_conf();
135 while(!thinfo){
136 thinfo = mk_sched_get_thread_conf();
139 /* Glibc doesn't export to user space the gettid() syscall */
140 thinfo->pid = syscall(__NR_gettid);
142 mk_sched_set_thread_poll(thconf->epoll_fd);
143 mk_epoll_init(thconf->epoll_fd, callers, thconf->max_events);
145 return 0;
148 struct request_idx *mk_sched_get_request_index()
150 return (struct request_idx *) pthread_getspecific(request_index);
153 void mk_sched_set_request_index(struct request_idx *ri)
155 pthread_setspecific(request_index, (void *)ri);
158 void mk_sched_set_thread_poll(int epoll)
160 pthread_setspecific(epoll_fd, (void *) epoll);
163 int mk_sched_get_thread_poll()
165 return (int) pthread_getspecific(epoll_fd);
168 struct sched_list_node *mk_sched_get_thread_conf()
170 struct sched_list_node *node;
171 pthread_t current;
173 current = pthread_self();
174 node = sched_list;
175 while(node){
176 if(pthread_equal(node->tid, current) != 0){
177 return node;
179 node = node->next;
182 return NULL;
187 void mk_sched_update_thread_status(int active, int closed)
189 struct sched_list_node *thnode;
191 if(config->cheetah == VAR_OFF){
192 return;
195 thnode = mk_sched_get_thread_conf();
197 switch(active){
198 case MK_SCHEDULER_ACTIVE_UP:
199 thnode->active_requests++;
200 break;
201 case MK_SCHEDULER_ACTIVE_DOWN:
202 thnode->active_requests--;
203 break;
206 switch(closed){
207 case MK_SCHEDULER_CLOSED_UP:
208 thnode->closed_requests++;
209 break;
210 case MK_SCHEDULER_CLOSED_DOWN:
211 thnode->closed_requests--;
212 break;