-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathterm.c
More file actions
161 lines (136 loc) · 4.91 KB
/
Copy pathterm.c
File metadata and controls
161 lines (136 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//==========================================================
// admin.c
// Authors: Madeline Jiang (100%)
// Work division: Added the semaphores and locks back in
//==========================================================
#define _BRD_SOURCE
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "simos.h"
//=========================================================================
// Terminal manager is responsible for printing an output string to terminal.
// When there is a term output, the process has to be in eWait state and
// we insert both pid and the output string to the terminal queue.
// After terminal output is done, we need to put process back to ready state,
// which has to be done by the process manager.
// The terminal can only put process in endWait queue and set the interrupt.
//=========================================================================
// terminal output file name and file descriptor
// write terminal output to a file, to avoid messy printout
#define termFN "terminal.out"
FILE *fterm;
void terminal_output (int pid, char *outstr);
//=========================================================================
// terminal output queue
// implemented as a list with head and tail pointers
//=========================================================================
typedef struct TermQnodeStruct
{ int pid, type;
char *str;
struct TermQnodeStruct *next;
} TermQnode;
TermQnode *termQhead = NULL;
TermQnode *termQtail = NULL;
// if terminal queue is empty, wait on term_semaq
// for each insersion, signal term_semaq
// essentially, term_semaq.count keeps track of #req in the queue
sem_t term_semaq;
// for access the queue head and queue tail
sem_t term_mutex;
// dump terminal queue is not inside the terminal thread,
// only called by admin.c
void dump_termio_queue ()
{ TermQnode *node;
printf ("******************** Term Queue Dump\n");
node = termQhead;
while (node != NULL)
{ printf ("%d, %s\n", node->pid, node->str);
node = node->next;
}
printf ("\n");
}
// insert terminal queue is not inside the terminal thread, but called by
// the main thread when terminal output is needed (only in cpu.c, process.c)
void insert_termio (pid, outstr, type)
int pid, type;
char *outstr;
{ TermQnode *node;
if (Debug) printf ("Insert term queue %d %s\n", pid, outstr);
node = (TermQnode *) malloc (sizeof (TermQnode));
node->pid = pid;
node->str = outstr;
node->type = type;
node->next = NULL;
sem_wait(&term_mutex);
if (termQtail == NULL) // termQhead would be NULL also
{ termQtail = node; termQhead = node; }
else // insert to tail
{ termQtail->next = node; termQtail = node; }
if (Debug) dump_termio_queue ();
sem_post(&term_semaq);
sem_post(&term_mutex);
}
// remove the termIO job from queue and call terminal_output for printing
// after printing, put the job to endWait list and set endWait interrupt
void handle_one_termio ()
{ TermQnode *node;
sem_wait(&term_semaq);
sem_wait(&term_mutex);
if (Debug) dump_termio_queue ();
if (termQhead == NULL)
printf ("No process in terminal queue!!!\n");
else
{ node = termQhead;
terminal_output (node->pid, node->str);
if (node->type != endIO)
{ insert_endWait_process (node->pid);
set_interrupt (endWaitInterrupt);
printf("---------------------------------------------------------------------------------\n");
} // if it is the endIO type, then job done, just clean termio queue
if (Debug) printf ("Remove term queue %d %s\n", node->pid, node->str);
termQhead = node->next;
if (termQhead == NULL) termQtail = NULL;
free (node->str); free (node);
if (Debug) dump_termio_queue ();
}
sem_post(&term_mutex);
}
//=====================================================
// IO function, loop on handle_one_termio to process the termio requests
// This has to be a separate thread to loop on the termio_one_handler
//=====================================================
// pretent to take a certain amount of time by sleeping printTime
// output is now simply printf, but it should be sent to client terminal
void terminal_output (pid, outstr)
int pid;
char *outstr;
{
fprintf (fterm, "pid %d: %s\n", pid, outstr);
fflush (fterm);
usleep (termPrintTime);
}
void *termIO ()
{
while (systemActive) handle_one_termio ();
if (Debug) printf ("TermIO loop has ended\n");
}
pthread_t termThread;
void start_terminal ()
{ int ret;
ret = sem_init(&term_mutex, 0, 1);
ret = sem_init(&term_semaq, 0, 0);
fterm = fopen (termFN, "w");
ret = pthread_create (&termThread, NULL, termIO, NULL);
if (ret < 0) printf ("TermIO thread creation problem\n");
else printf ("TermIO thread has been created successsfully\n");
}
void end_terminal ()
{ int ret;
sem_post(&term_semaq);
fclose (fterm);
ret = pthread_join (termThread, NULL);
printf ("TermIO thread has terminated %d\n", ret);
}