Project

General

Profile

Statistics
| Revision:

root / branches / simulator / projects / simulator / simulator / core / robot.c @ 997

History | View | Annotate | Download (3.98 KB)

1
/**
2
 * @file robot.c
3
 * @author Colony Project
4
 * @brief Simulator Robot Management
5
 *
6
 * Contains implementations of functions managing robots
7
 * in the simulator, including process control and memory
8
 * management.
9
 **/
10

    
11
#include <stdlib.h>
12
#include <stdio.h>
13
#include <string.h>
14

    
15
#include <unistd.h>
16
#include <signal.h>
17
#include <sys/wait.h>
18
#include <robot_shared.h>
19
#include <sys/ipc.h>
20
#include <sys/types.h>
21
#include <sys/shm.h>
22
#include <errno.h>
23

    
24
#include "robot.h"
25

    
26
void sig_chld_handler(int sig);
27

    
28
// global variables
29
int first_available_id = 0;
30
// an expanding array of robots
31
Robot* robots = NULL;
32
int robots_size = 0;
33

    
34
int iterator_pos = 0;
35

    
36
int robots_initialize(void)
37
{
38
        int i;
39
        if (signal(SIGCHLD, sig_chld_handler) == SIG_ERR)
40
                return -1;
41

    
42
        robots_size = 10;
43
        robots = (Robot*)malloc(sizeof(Robot) * robots_size);
44
        if (!robots)
45
                return -1;
46
        memset(robots, 0, sizeof(Robot) * robots_size);
47
        for (i = 0; i < robots_size; i++)
48
                robots[i].id = -1;
49

    
50
        return 0;
51
}
52

    
53
/**
54
 * Creates a new robot. Returns its id on
55
 * success, or a negative integer on failure.
56
 **/
57
int robot_create(char *execname)
58
{
59
        int pid;
60
        int id = first_available_id;
61
        Robot* r = &robots[id];
62
        // do shared memory stuff here
63
        key_t key = IPC_PRIVATE;
64
        //Memory accessible only to children with r/w privileges
65
        r->sharedMemID = shmget(key, sizeof(RobotShared), IPC_CREAT | 0666);
66
        
67
        if(r->sharedMemID < 0)
68
        {
69
                fprintf(stderr, "Failed to get shared memory.\n");
70
                return -1;
71
        }
72

    
73
        r->shared = (RobotShared*)shmat(r->sharedMemID, NULL, 0);
74
        
75
        if(!(r->shared))
76
        {        
77
                //Free shared memory region
78
                if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
79
                        fprintf(stderr, "Failed to free shared memory.\n");
80
                       
81
                fprintf(stderr, "Error attaching memory to parent.\n");
82
                return -1;
83
        }
84
        
85
        // Initialize robot structure here
86
        r->shared->motor1 = 0;
87
        r->shared->motor2 = 0;
88
        r->id = id;
89

    
90
        if((pid = fork()) < 0)
91
        {
92
                //Free Shared Memory Region
93
                if (!shmdt(r->shared))
94
                        fprintf(stderr, "Failed to free shared memory.\n");
95
                
96
                if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
97
                        fprintf(stderr, "Failed to free shared memory.\n");
98

    
99
                r->id = -1;
100
                fprintf(stderr, "Failed to fork robot process.\n");
101
                return -1;
102
        }
103
        
104

    
105
        if(!pid)
106
        {
107
          char var[21];
108
          /* restore default sigchld handler */
109
          signal(SIGCHLD, SIG_DFL);
110
          sprintf(var, "memory_id=%d", r->sharedMemID);
111
          putenv(var);
112
          //TODO: keep the other env. stuff around
113
          execv(execname, NULL);
114
          fprintf(stderr, "exec failed to run child process.\n");
115
          exit(-1);
116
        }
117
        else
118
        {
119
                r->pid = pid;
120
                do {
121
                        first_available_id++;
122
                } while (first_available_id < robots_size &&
123
                                robots[first_available_id].id != 0);
124
                // resize the array if necessary
125
                if (first_available_id >= robots_size)
126
                {
127
                        robots_size *= 2;
128
                        robots = realloc(robots, sizeof(Robot) * robots_size);
129
                        if (!robots)
130
                        {
131
                                fprintf(stderr, "Out of memory.\n");
132
                                return -1;
133
                        }
134
                }
135
        }
136
        
137
        return id;
138
}
139

    
140
/**
141
 * Frees all resources associated with a robot, including
142
 * killing its process if necessary.
143
 *
144
 * @return zero on success, nonzero on failure
145
 **/
146
int robot_destroy(int id)
147
{
148
        Robot* r;
149

    
150
        if (id < 0 || id >= robots_size)
151
                return -1;
152
        r = &robots[id];
153
        if (r->id == 0)
154
                return -1;
155

    
156
    if (!shmdt(r->shared))
157
        {
158
                fprintf(stderr, "Failed to free shared memory.\n");
159
                return -1;
160
        }
161
        if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
162
        {
163
                fprintf(stderr, "Failed to free shared memory.\n");
164
                return -1;
165
        }
166

    
167
        memset(r, 0, sizeof(Robot));
168
        r->id = -1;
169

    
170
        if (id < first_available_id)
171
                first_available_id = 0;
172
        
173
        return 0;
174
}
175

    
176
void robot_iterator_reset(void)
177
{
178
        iterator_pos = 0;
179
}
180

    
181
// note: addresses may change, replace with
182
// allocated memory
183
Robot* robot_iterator_next(void)
184
{
185
        while (iterator_pos < robots_size && 
186
                        robots[iterator_pos].id == -1)
187
                iterator_pos++;
188
        
189
        if (iterator_pos >= robots_size)
190
                return NULL;
191
        
192
        return &(robots[iterator_pos]);
193
}
194

    
195
void sig_chld_handler(int sig)
196
{
197
        pid_t pid;
198
        int cstat;
199

    
200
        printf("SIGCHLD: parent waiting\n");
201

    
202
        pid = waitpid(0, &cstat, WUNTRACED);
203

    
204
        printf("got %d from %d\n", cstat, pid);
205

    
206
        kill(pid, SIGCONT);
207
}
208