00001
00013 #include "io_device.h"
00014
00022 static STAILQ_HEAD(io_requests, io_entry) io_request_head;
00026 static uint16_t ioreq_count;
00030 static pthread_mutex_t fifo_lock = PTHREAD_MUTEX_INITIALIZER;
00035 static pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER;
00039 static pthread_mutex_t wait_lock = PTHREAD_MUTEX_INITIALIZER;
00044 static pthread_mutex_t request_lock = PTHREAD_MUTEX_INITIALIZER;
00052 static int io_device_should_exit;
00053
00054 extern proc_t **proc_table;
00055 extern int max_proc;
00056
00057
00068 static void *
00069 thread_io_device(void *parg)
00070 {
00071 io_entry_t *req;
00072 struct timespec timeout;
00073 int num;
00074
00075 printf("--> Thread DEVICE I/O avviato [Tmin=%d, Tmax=%d]\n",
00076 io_dev.Tmin, io_dev.Tmax);
00077
00078 while (!io_device_should_exit) {
00079 pthread_mutex_lock(&wait_lock);
00080 while ((ioreq_count == 0) && !io_device_should_exit) {
00081 pthread_cond_wait(&wait_cond, &wait_lock);
00082 }
00083
00084 if (io_device_should_exit && (ioreq_count == 0)) {
00085 pthread_mutex_unlock(&wait_lock);
00086 break;
00087 }
00088
00089
00090
00091
00092
00093
00094 req = STAILQ_FIRST(&io_request_head);
00095 assert(req);
00096
00097 pthread_mutex_lock(&fifo_lock);
00098 STAILQ_REMOVE(&io_request_head, req, io_entry, entries);
00099 ioreq_count--;
00100 pthread_mutex_unlock(&fifo_lock);
00101
00102
00103
00104
00105
00106
00107 num = bounded_rand(io_dev.Tmin, io_dev.Tmax);
00108 timeout.tv_sec = 0;
00109 timeout.tv_nsec = num * 1000000;
00110 nanosleep(&timeout, NULL);
00111 fprintf(LOG_FILE(req->procnum),
00112 "Richiesta d'accesso servita in %d ms\n", num);
00113
00114
00115
00116
00117
00118 io_dev.req_count++;
00119 proc_table[req->procnum]->stats.io_requests++;
00120 proc_table[req->procnum]->stats.time_elapsed += num;
00121 pthread_mutex_unlock(&wait_lock);
00122 pthread_cond_signal(&proc_table[req->procnum]->io_cond);
00123 XFREE(req);
00124 }
00125 printf("<-- Thread DEVICE I/O terminato\n");
00126 pthread_exit(NULL);
00127 }
00128
00129
00142 pthread_t *io_device_init(int min, int max)
00143 {
00144 pthread_t *tid = XMALLOC(pthread_t, 1);
00145 int ret;
00146
00147 if (io_dev.Tmax > io_dev.Tmin)
00148 io_dev.Tmax = io_dev.Tmin;
00149 else {
00150 io_dev.Tmin = min;
00151 io_dev.Tmax = max;
00152 }
00153 io_device_should_exit = 0;
00154 ioreq_count = 0;
00155 io_dev.req_count = 0;
00156 STAILQ_INIT(&io_request_head);
00157 ret = pthread_create(tid, NULL, &thread_io_device, NULL);
00158
00159 return (ret == 0) ? tid : NULL;
00160 }
00161
00162
00174 int io_device_read(uint16_t procnum)
00175 {
00176 io_entry_t *req;
00177 int ret;
00178
00179 pthread_mutex_lock(&request_lock);
00180
00181 if (!io_device_should_exit) {
00182 pthread_mutex_lock(&wait_lock);
00183 req = XMALLOC(io_entry_t, 1);
00184 req->pid = proc_table[procnum]->pid;
00185 req->procnum = procnum;
00186 pthread_mutex_lock(&fifo_lock);
00187 if (STAILQ_EMPTY(&io_request_head))
00188 STAILQ_INSERT_HEAD(&io_request_head, req, entries);
00189 else
00190 STAILQ_INSERT_TAIL(&io_request_head, req, entries);
00191 ioreq_count++;
00192 pthread_mutex_unlock(&fifo_lock);
00193
00194 fprintf(LOG_FILE(procnum),
00195 "\nRichiesta d'accesso a dispositivo I/O accodata\n");
00196
00197 pthread_mutex_unlock(&wait_lock);
00198 pthread_cond_signal(&wait_cond);
00199 ret = 1;
00200 } else
00201 ret = 0;
00202
00203 pthread_mutex_unlock(&request_lock);
00204
00205 return ret;
00206 }
00207
00208
00215 void tell_io_device_to_exit()
00216 {
00217 pthread_mutex_lock(&request_lock);
00218 io_device_should_exit = 1;
00219 pthread_mutex_unlock(&request_lock);
00220 pthread_cond_signal(&wait_cond);
00221 }
00222