SlideShare a Scribd company logo
1 of 70
“Social Change”
Program Transcript
HOLLY HOEY: So Maurice, as we talk about social change, I
know there's a
story behind how you got into this field. I can just sense your
passion and
enthusiasm for what you do.
MAURICE WILLIAMS: Well, I've always had an interest in the
human condition.
My undergrad was in psychology, so we studied a lot about the
mind, human
behavior. I've always been inquisitive. I want to know; how did
we get here, who
are we, why are we so different, why are we so alike, what
makes us who we
are? And so, literally, that's why I got into it.
Now, as I started working in the field though, I saw that, wow,
it's not about
being inquisitive. There's really a lot of needs out here for
people. There's a lot
of pain out here. It's a lot of trauma, a lot of grief, a lot of loss.
And I come from
a family that has always been very community focused.
And so I got into working with people with disabilities. And
then next, I worked
with adults who were on assistance, tenants assistance. And
then I ended up
working with children. And now it's like, "Wow, there it is."
Children have such a
vulnerability, but such a purity. I can connect with them,
because children always
remind me that we all were one of them at one time. And I'm
fortunate enough to
have gotten into a field that keeps me focused on, like Holly
asked, What am I
going to do good today? Who am I going to help? Not really
save, but who am I
going to help progress further in their life."
HOLLY HOEY: What about you Andrea?
ANDREA INGRAM: Well, I grew up in a large family, a lot of
kids, and I was in
the middle. So middle children, we do a lot of mediating and all
this kind of stuff.
But, I also grew up with a very keen sense of justice and
fairness. When there
are seven kids in the family, you learn that life is not fair. And
my parents had a
strong sense of justice also, and
were great examples.
So when I went out into the world, I felt an obligation, a
responsibility to try to
make life better for people that didn't have it as well as I did.
Because to me, it's a
sense of justice and fairness to include people in the mainstream
who are left out,
for whatever reason. They're left out because of poverty, they're
left out because
of mental illness, or there are left out because of their
personality. They're just left
out because of relationships.
So it's just because of, I think, being raised with a keen sense of
fairness and
justice and wanting to have an impact on that.
I found that I really loved crisis work, because when people are
in crisis there's
such energy there and motivation to make things different. And
there's a real
opportunity to make things different and to make some really
significant changes
and reach some really significant resolutions in your life that
really might put you
on a different path.
HOLLY HOEY: I say that I'm in this field by default. But it
worked out to my
benefit, because I absolutely love what I do. I wasn't a middle
child, but I've
always been a mediator. Always. "Are you OK? Is everyone
OK? Let's make sure
everybody gets along." And so that's just my personality.
But I have a degree in interior design. And so I did design work
for five years.
And I race walked a marathon for Leukemia Society, and we
had to raise money.
Here we go. Here goes my life story. And I had to raise money,
which I found to
be so simple. And people kept saying, "How are you raising all
that money?" And
I said, "It's because I believe in it." If I could talk about it and I
believed in it, and I
really had a case for why I was raising money, I found it to be
very easy.
And so here goes my career change. I loved it. And I said, "I'm
not fulfilled in
my previous job." And I just said, "I'm going to make a life
change." And it
was the best change that I made. And 12 years later, here I am. I
love it at
United Way.
And I just feel that I connect the dots. That's my job. I connect
the dots. I
connect the dots with my volunteers, with donors, to people that
need help. And
United Way does the same thing with partners. And I just feel
that that's where
my skill set is. If I can bring these people together to effect
change, I've done
my job.
So we're talking about how our organizations influence social
change. And I
think this is actually the most exciting part to discuss, because
being at United
Way for over 12 years, I think that my job every day is
extremely rewarding and
fulfilling.
What United Way of Central Maryland does is to again,
mobilize the community
to improve people's lives. We are touching the lives and
changing lives as it
relates to helping people sustain their lives, to stabilize, and
then getting them
out of that spiraling poverty and getting them to self-
sufficiency. My job is to
educate and communicate and inform individuals about the most
pressing
needs in this community.
MAURICE WILLIAMS: I, like you, Holly, believe that social
change is very, very
important for our organization as well, the Williams Life
Center. We service
people who are born into the number one institution, the first
institution that
they'll ever be a part of, which is the family. Unfortunately,
their families fall apart
for whatever reasons, neglect, abuse, drugs, incarceration. Some
families and
some parents want to take care of the kids, but they just don't
have the
resources and the capabilities to do so. And so we at the
Williams Life Center
bring them in.
Some children come into our program and they've already lost a
lot. And maybe
they're now 14 already when they come into the system, and
some of them have
a long way to go. And they may falter and they may not be
successful in the
program that we provide to them. But then there are others,
which far outweigh
the ones that don't make it, that will come in and although they
have the
emotional baggage that they have, and the traumas that they've
experienced, we
watch them grow and we watch them become connected to a
family.
And that is so rewarding, because we see that as our duty to
ensure that these
children, no matter what their previous life would have been
like, that when they
come to our agency we're going to take care of them, bottom
line. We're going to
take care of them. And if they're in an environment that is not
meeting the
standard, we move them. And then those that aren't meeting the
standard, but we
can work with them to get them higher, we do that. And so
that's how we believe
we affect social change. Because this is another child who may
not grow up to be
an abuser himself.
ANDREA INGRAM: Well, to me, social change is very
personal. You talked
about volunteers. You talked about your families and the kids. I
think large
change starts with one person, and it goes from that person to
their family, to
their congregation.
An example that I would like to talk a little bit about is, we do a
lot of services for
people with mental illness. And they're in our shelter programs,
but we also have
a mobile crisis team and we go out with the police. We also do
some training with
the Police Department on how to better manage situations with a
person who's
perhaps having a psychotic episode, may be behaviorally out of
control, resulting
in some family conflict, and so forth.
There's one person that we respond to all the time. When she's
not in treatment,
it can be pretty outrageous, including challenging the police,
very confrontational.
It could even be sexually oriented. When the police went to
lunch at this day
program, there she was. And it was at a point in her life where
she was in
treatment. And the police were just amazed. They sat down with
her, were able to
talk with her, see her when she is in treatment and is doing
well. And were even
able to talk to her about, how should we behave when we come
out and you're in
crisis? So that she could even have some input into how the
police and the
mobile crisis team would respond to her.
That one thing transfers to other police officers, transfers to
how they act when
they respond to other people who are having a mental health
crisis. Because they
can see the person behind the crisis. And when you see the
person behind the
crisis, you handle it a little differently. So that to me is social
change, one person
at a time.
MAURICE WILLIAMS: When we think of social change,
sometimes I think we
think of somebody standing behind a podium saying, "Let's do
it," and there's
hundreds of thousands of people out there on the lawn listening.
But it's really
one person at a time.
And sometimes, in our jobs, we have to remind ourselves how
important
what we do really is.
I was in Walmart two weeks ago, and a foster family came up to
me and said,
"Hey, Mr. Williams." And I turned around and it was a 16-year
old who I had
placed there over a year ago with her foster mother. And the 16-
year old has a
son who was born about a year or so ago. The son was born with
extreme
health needs. And so working with this child, she broke down.
She said, "I'm in
twelfth grade. My child is sick." The child was in the hospital
for like three
months at a time. And we said to her, "We will help you through
this. We're
going to ensure that you graduate. We're going to ensure that
this baby is
taken care of." And we stuck with her.
And so when I walked away after we spoke, I looked back at
them again and I
said to myself, "Wow, that could have never happened had we
not really
worked to keep this girl together, to keep this baby together, to
keep this
family together." So sometimes, little glimpses will come that
says, "You know
what Maurice, what you guys do is really important."
And so it is one individual at a time. It really is.
© 2013 Laureate Education, Inc. 4
__MACOSX/._assign3
assign3/.DS_Store
__MACOSX/assign3/._.DS_Store
assign3/assign3_part2/list.c
#include <stdio.h>
#include "list.h"
/* list helper functions */
int list_size(thread_info_list *list)
{
int cnt = 0;
if (!list) return -1;
pthread_mutex_lock(&list->lock);
list_elem *le = list->head;
while (le) {
cnt++;
le = le->next;
}
pthread_mutex_unlock(&list->lock);
return cnt;
}
int list_insert_head(thread_info_list *list, list_elem *new)
{
if (!list || !new) return -1;
pthread_mutex_lock(&list->lock);
new->next = list->head;
new->prev = 0;
if (new->next) {
new->next->prev = new;
}
list->head = new;
if (list->tail == 0) {
list->tail = new;
}
pthread_mutex_unlock(&list->lock);
return 0;
}
int list_insert_tail(thread_info_list *list, list_elem *new)
{
if (!list || !new) return -1;
pthread_mutex_lock(&list->lock);
new->prev = list->tail;
new->next = 0;
if (new->prev) {
new->prev->next = new;
}
list->tail = new;
if (list->head == 0) {
list->head = new;
}
pthread_mutex_unlock(&list->lock);
return 0;
}
int list_remove(thread_info_list *list, list_elem *old)
{
if (!old || !list) return -1;
pthread_mutex_lock(&list->lock);
if (old->next) {
old->next->prev = old->prev;
}
if (old->prev) {
old->prev->next = old->next;
}
if (list->tail == old) {
list->tail = old->prev;
}
if (list->head == old) {
list->head = old->next;
}
old->next = old->prev = 0;
pthread_mutex_unlock(&list->lock);
return 0;
}
void print_list(thread_info_list *list)
{
pthread_mutex_lock(&list->lock);
list_elem *le = list->head;
while (le) {
printf("0x%X,", (unsigned int)le->info);
le = le->next;
}
pthread_mutex_unlock(&list->lock);
printf("n");
}
__MACOSX/assign3/assign3_part2/._list.c
assign3/assign3_part2/worker.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "scheduler.h"
/****************************************************
***************************
*
* Implement these functions.
*
*****************************************************
*************************/
/* Handler for SIGTERM signal */
void cancel_thread()
{
printf("Thread %u: terminating.n", (unsigned
int)pthread_self());
/* signal that done in queue */
sem_post(&queue_sem);
pthread_exit(NULL);
}
/* TODO: Handle the SIGUSR1 signal */
void suspend_thread()
{
printf("Thread %u: suspending.n", (unsigned
int)pthread_self());
/*add your code here to wait for a resume signal from the
scheduler*/
printf("Thread %u: resuming.n",(unsigned int)
pthread_self());
}
/****************************************************
***************************
*
*
*
*****************************************************
*************************/
/*
* waits to gain access to the scheduler queue.
*/
static int enter_scheduler_queue(thread_info_t *info)
{
/*
* wait for available room in queue.
* create a new list entry for this thread
* store this thread info in the new entry.
*/
sem_wait(&queue_sem);
list_elem *item = (list_elem*)malloc(sizeof(list_elem));
info->le = item;
item->info = info;
item->prev = 0;
item->next = 0;
list_insert_tail(&sched_queue, item);
return 0;
}
/*
* leaves the scheduler queue
*/
void leave_scheduler_queue(thread_info_t *info)
{
printf("Thread %lu: leaving scheduler queue.n", info-
>thrid);
/*
* remove the given worker from queue
* clean up the memory that we malloc'd for the list
* clean up the memory that was passed to us
*/
list_remove(&sched_queue, info->le);
free(info->le);
free(info);
}
/*
* Initialize thread, enter scheduling queue, and execute
instructions.
* arg is a pointer to thread_info_t
*/
void *start_worker(void *arg)
{
thread_info_t *info = (thread_info_t *) arg;
float calc = 0.8;
int j = 0;
/* TODO: Block SIGALRM and SIGUSR2. */
/* TODO: Unblock SIGUSR1 and SIGTERM. */
/* compete with other threads to enter queue. */
if (enter_scheduler_queue(info)) {
printf("Thread %lu: failure entering scheduler queue -
%sn", info->thrid, strerror(errno));
free (info);
pthread_exit(0);
}
printf("Thread %lu: in scheduler queue.n", info->thrid);
suspend_thread();
while (1) {
/* do some meaningless work... */
for (j = 0; j < 10000000; j++) {
calc = 4.0 * calc * (1.0 - calc);
}
}
}
__MACOSX/assign3/assign3_part2/._worker.c
assign3/assign3_part2/Makefile
CC = gcc
CCOPTS = -c -g -Wall
LINKOPTS = -g -pthread -Wall
EXEC=scheduler
OBJECTS=scheduler.o worker.o list.o smp5_tests.o testrunner.o
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CC) $(LINKOPTS) -o [email protected] $^ -lrt
%.o:%.c
$(CC) $(CCOPTS) -o [email protected] $^
clean:
- $(RM) $(EXEC)
- $(RM) $(OBJECTS)
- $(RM) *~
- $(RM) core.*
test: scheduler
- ./scheduler -test -f0 rr
- killall -q -KILL scheduler; true
pretty:
indent *.c *.h -kr
__MACOSX/assign3/assign3_part2/._Makefile
assign3/assign3_part2/scheduler.h
#ifndef __SCHEDULER_H_
#define __SCHEDULER_H_
#include <pthread.h>
#include <semaphore.h>
#include "list.h"
#define QUANTUM 1
/* typedefs */
typedef struct thread_info {
pthread_t thrid;
int quanta;
list_elem* le;
/*added for evalution bookkeeping*/
struct timespec suspend_time;
struct timespec resume_time;
long wait_time;
long run_time;
} thread_info_t;
/* functions */
void *start_worker(void *);
long time_difference(const struct timespec*, const struct
timespec*);
int smp5_main(int argc, const char** argv);
/* shared variables */
extern sem_t queue_sem; /* semaphore for scheduler
queue */
extern thread_info_list sched_queue; /* list of current
workers */
#endif /* __SCHEDULER_H_ */
__MACOSX/assign3/assign3_part2/._scheduler.h
assign3/assign3_part2/smp5_tests.c
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "testrunner.h"
#include "list.h"
#include "scheduler.h"
#include "worker.h"
//#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);}
while(0)
#define quit_if(cond) do {if (cond) {printf("Line
%d.",__LINE__);exit(EXIT_FAILURE);}} while(0)
void args_to_nums(int argc, const char **argv, int
*num_workers, int *queue_size, int **quanta) {
int i;
quit_if(argc < 4);
*num_workers = atoi(argv[1]);
*queue_size = atoi(argv[2]);
*quanta = malloc(*num_workers * sizeof(int));
quit_if(*quanta == NULL);
for(i=3;i<argc;i++)
quanta[0][i-3] = atoi(argv[i]);
}
void nums_to_args(int num_workers, int queue_size, int
*quanta, int *argc, char ***argv) {
int i;
*argc = num_workers+3;
*argv = malloc(*argc*sizeof(char *));
quit_if(*argv==NULL);
argv[0][0] = "scheduler";
argv[0][1] = malloc(3*sizeof(char));
quit_if(argv[0][1]==NULL);
sprintf(argv[0][1],"%d",num_workers);
argv[0][2] = malloc(3*sizeof(char));
quit_if(argv[0][2]==NULL);
sprintf(argv[0][2],"%d",queue_size);
for(i=0;i<num_workers;i++) {
argv[0][i+3] = malloc(3*sizeof(char));
quit_if(argv[0][i+3]==NULL);
sprintf(argv[0][i+3],"%d",quanta[i]);
}
argv[0][i+3]=NULL;
}
/* Prepare input, reroute file descriptors, and run the program.
*/
void run_test(int argc, const char **argv)
{
//int fork_pid = fork();
//if (fork_pid == 0) {
/* Reroute standard file descriptors */
freopen("smp5.out", "w", stdout);
/* Run the program */
quit_if(smp5_main(argc, argv) != EXIT_SUCCESS);
fclose(stdout);
//} else if (fork_pid > 0) {
//waitpid(fork_pid, 0, 0);
//} else {
//fprintf(stderr, "run_test: fork() errorn");
//}
}
int test_output(FILE *stream, int nw, int qs, int *q) {
int queue_size, queue_index;
int num_workers, worker_index;
int rv, in_queue, term, susp;
unsigned long *queue, *workers, tid, prev, newwork, dummyl;
int *remaining, *quanta;
char dummyc;
float tot_wait, tot_run, ave_wait, ave_run;
int my_run, my_wait;
rv = fscanf(stream,"Main: running %d workers with queue size
%d for quanta:n",&num_workers, &queue_size);
quit_if(rv != 2 || num_workers != nw || queue_size != qs);
queue = malloc(queue_size*sizeof(long));
workers = malloc(num_workers*sizeof(long));
quanta = malloc(num_workers*sizeof(int));
remaining = malloc(queue_size*sizeof(int));
for(worker_index=0;worker_index<num_workers;worker_index
++) {
quit_if(fscanf(stream, " %d", quanta+worker_index) != 1);
quit_if(quanta[worker_index]!=q[worker_index]);
}
fscanf(stream,"n");
for(worker_index=0;worker_index<num_workers;worker_index
++) {
quit_if(fscanf(stream, "Main: detaching worker thread
%lu.n",workers+worker_index) != 1);
}
quit_if(fscanf(stream, "Main: waiting for scheduler
%lu.n",&dummyl) != 1);
for(;queue_index<queue_size;queue[queue_index++]=0);
worker_index = queue_index=0;
in_queue = 0;
quit_if(fscanf(stream, "Scheduler: waiting for
workers.%c",&dummyc)!=1 || dummyc != 'n');
for(queue_index = 0;queue_index < queue_size &&
queue_index < num_workers;queue_index++) {
quit_if(fscanf(stream, "Thread %lu: in scheduler
queue.n",&tid)!= 1 || tid != workers[worker_index]);
quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)!= 1
|| tid != workers[worker_index]);
queue[queue_index]=tid;
remaining[queue_index] = quanta[worker_index];
worker_index++;
in_queue++;
}
my_run=0;
my_wait = num_workers;
queue_index = 0;
term = susp = 0;
while(worker_index < num_workers || in_queue > 0) {
while(!queue[queue_index])
queue_index= (queue_index+1)%queue_size;
quit_if(fscanf(stream, "Scheduler:
scheduling.%c",&dummyc)!=1 || dummyc != 'n');
quit_if(fscanf(stream, "Scheduler: resuming %lu.n",&tid) !=
1);
quit_if( tid != queue[queue_index]);
if (prev == tid) {
if(term) {
quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid)
!= 1 || tid != prev);
} else if (susp){
quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)
!= 1);
quit_if( tid != prev);
}
quit_if(fscanf(stream, "Thread %lu: resuming.n",&tid) !=
1);
quit_if(tid != queue[queue_index]);
} else {
quit_if(fscanf(stream, "Thread %lu: resuming.n",&tid) != 1
|| tid != queue[queue_index]);
if(term) {
if(queue_size == 1)
quit_if(fscanf(stream, "Scheduler: waiting for
workers.%c",&dummyc)!=1 || dummyc!='n');
quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid)
!= 1 || tid != prev);
if (in_queue == queue_size) {
quit_if(fscanf(stream, "Thread %lu: in scheduler
queue.n",&tid)!=1||tid != newwork);
quit_if(fscanf(stream, "Thread %lu:
suspending.n",&tid)!=1 || tid!=newwork);
}
} else if (susp && in_queue>1){
quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)
!= 1);
quit_if( tid != prev);
prev = tid;
}
}
quit_if(fscanf(stream, "Scheduler: suspending %lu.n",&tid)
!= 1);
quit_if(tid != queue[queue_index]);
if(!--remaining[queue_index]) {
quit_if(fscanf(stream, "Thread %lu: leaving scheduler
queue.n",&tid)!=1 || tid != queue[queue_index]);
term = 1;
if(worker_index < num_workers) {
queue[queue_index] = workers[worker_index];
remaining[queue_index] = quanta[worker_index];
newwork = workers[worker_index];
worker_index++;
if(queue_size == 1) {
prev = tid;
quit_if(fscanf(stream, "Scheduler: waiting for
workers.%c",&dummyc)!=1 || dummyc!='n');
quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid)
!= 1 || tid != prev);
quit_if(fscanf(stream, "Thread %lu: in scheduler
queue.n",&tid)!= 1 || tid != newwork);
quit_if(fscanf(stream, "Thread %lu:
suspending.n",&tid)!= 1 || tid != newwork);
term = 0;
susp = 0;
my_wait++;
}
} else {
queue[queue_index] = 0;
in_queue--;
}
} else {
term = 0;
susp = 1;
}
prev = tid;
my_run++;
my_wait += in_queue+(num_workers-worker_index)-1+term;
queue_index= (queue_index+1)%queue_size;
}
quit_if(fscanf(stream, "Th%c",&dummyc) != 1);
if (dummyc=='r') {
quit_if(fscanf(stream, "ead %lu: terminating.nThe",&tid)!=1
|| tid != prev);
}
quit_if(fscanf(stream, " total wait time is %f
seconds.n",&tot_wait) != 1);
quit_if(fscanf(stream, "The total run time is %f
seconds.n",&tot_run) != 1);
quit_if(fscanf(stream, "The average wait time is %f
seconds.n",&ave_wait) != 1);
quit_if(fscanf(stream, "The average run time is %f
seconds.n",&ave_run) != 1);
if (dummyc=='e')
quit_if(fscanf(stream, "Thread %lu: terminating.nThe",&tid)
!= 1|| tid != prev);
quit_if(abs(tot_wait-my_wait)>1);
quit_if(abs(tot_run-my_run)>1);
quit_if(abs(tot_wait/num_workers-ave_wait)>.5);
quit_if(abs(tot_run/num_workers-ave_run)>.5);
return 0;
}
int general_test(int argc, const char **argv) {
FILE *f;
int nw, qs, *q;
run_test(argc,argv);
f = fopen("smp5.out","r");
args_to_nums(argc,argv,&nw,&qs,&q);
test_output(f,nw,qs,q);
return EXIT_SUCCESS;
}
int specific_test(int nw, int qs, int *q) {
FILE *f;
int argc;
char **argv;
nums_to_args(nw,qs,q,&argc,&argv);
run_test(argc,(const char **)argv);
f = fopen("smp5.out","r");
test_output(f,nw,qs,q);
return EXIT_SUCCESS;
}
int test_3_1_2_2_2() {
int q[3] = {2,2,2};
return specific_test(3,1,q);
}
int test_2_2_2_2() {
int q[2]={2,2};
return specific_test(2,2,q);
}
int test_5_7_1_2_1_2_1() {
int q[5] = {1,2,1,2,1};
return specific_test(5,7,q);
}
int test_4_1_1_2_3_4() {
int q[4] = {1,2,3,4};
return specific_test(4,1,q);
}
int test_3_3_4_3_2() {
int q[3] = {4,3,2};
return specific_test(3,3,q);
}
/*
* Main entry point for SMP% test harness
*/
int run_smp5_tests(int argc, const char **argv)
{
/* Tests can be invoked by matching their name or their
suite name
* or 'all' */
testentry_t tests[] = {
{"test_3_1_2_2_2", "rr", test_3_1_2_2_2},
{"test_2_2_2_2", "rr", test_2_2_2_2},
{"test_5_7_1_2_1_2_1", "rr", test_5_7_1_2_1_2_1},
{"test_4_1_1_2_3_4", "rr", test_4_1_1_2_3_4},
{"test_3_3_4_3_2", "rr", test_3_3_4_3_2},
{"general", "gen", general_test}
};
int result = run_testrunner(argc, argv, tests, sizeof(tests) /
sizeof(testentry_t));
unlink("smp5.out");
return result;
}
/* The real main function. */
int main(int argc, const char **argv)
{
if (argc > 1 && !strcmp(argv[1], "-test")) {
return run_smp5_tests(argc - 1, argv + 1);
} else {
return smp5_main(argc, argv);
}
}
__MACOSX/assign3/assign3_part2/._smp5_tests.c
assign3/assign3_part2/testrunner.h
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
typedef int (*test_fp) (int, const char **);
typedef struct {
const char *name;
const char *suite;
test_fp test_function;
} testentry_t;
int run_testrunner(int argc, const char **argv, testentry_t *
entries,
int entry_count);
void set_testrunner_default_timeout(int s);
void set_testrunner_timeout(int s);
__MACOSX/assign3/assign3_part2/._testrunner.h
assign3/assign3_part2/worker.h
#ifndef __WORKER_H_
#define __WORKER_H_
void cancel_thread();
void suspend_thread();
void leave_scheduler_queue(thread_info_t*);
#endif
__MACOSX/assign3/assign3_part2/._worker.h
assign3/assign3_part2/list.h
#ifndef __LIST_H_
#define __LIST_H_
#include <pthread.h>
typedef struct list_elem {
struct list_elem *prev;
struct list_elem *next;
void *info;
} list_elem;
typedef struct thread_info_list {
list_elem *head;
list_elem *tail;
pthread_mutex_t lock;
} thread_info_list;
int list_size(thread_info_list *list);
int list_insert_head(thread_info_list *list, list_elem *new);
int list_insert_tail(thread_info_list *list, list_elem *new);
int list_remove(thread_info_list *list, list_elem *new);
void print_list(thread_info_list *list);
#endif /* __LIST_H_ */
__MACOSX/assign3/assign3_part2/._list.h
assign3/assign3_part2/README.txt
SMP5: Scheduler with Signals
============================
This MP is a variation of SMP4.
In the last MP, we built a simulated OS process scheduler. The
scheduler can
hold only a certain number of processes (workers) at one time.
Once the process
has been accepted into the scheduler, the scheduler decides in
what order the
processes execute. We implemented two scheduling algorithms:
FIFO and Round
Robin.
In this MP, we are to simulate a time-sharing system by using
signals and
timers. We will only implement the Round Robin algorithm.
Instead of using
iterations to model the concept of "time slices" (as in the last
MP), we use
interval timers. The scheduler is installed with an interval
timer. The timer
starts ticking when the scheduler picks a thread to use the CPU
which in turn
signals the thread when its time slice is finished thus allowing
the scheduler
to pick another thread and so on. When a thread has completely
finished its work
it leaves the scheduler to allow a waiting thread to enter. Please
note that in
this MP, only the timer and scheduler send signals. The threads
passively handle
the signals without signaling back to the scheduler.
The program takes a number of arguments. Arg1 determines the
number of jobs
(threads in our implementation) created; arg2 specifies the
queue size of the
scheduler. Arg3 through argN gives the duration (the required
time slices to
complete a job) of each job. Hence if we create 2 jobs, we
should supply arg3
and arg4 for the required duration. You can assume that the
autograder will
always supply the correct number of arguments and hence you
do not have to
detect invalid input.
Here is an example of program output, once the program is
complete:
% scheduler 3 2 3 2 3
Main: running 3 workers with queue size 2 for quanta:
3 2 3
Main: detaching worker thread 3075926960.
Main: detaching worker thread 3065437104.
Main: detaching worker thread 3054947248.
Main: waiting for scheduler 3086416816.
Scheduler: waiting for workers.
Thread 3075926960: in scheduler queue.
Thread 3075926960: suspending.
Thread 3065437104: in scheduler queue.
Thread 3065437104: suspending.
Scheduler: scheduling.
Scheduler: resuming 3075926960.
Thread 3075926960: resuming.
Scheduler: suspending 3075926960.
Scheduler: scheduling.
Scheduler: resuming 3065437104.
Thread 3065437104: resuming.
Thread 3075926960: suspending.
Scheduler: suspending 3065437104.
Scheduler: scheduling.
Scheduler: resuming 3075926960.
Thread 3075926960: resuming.
Thread 3065437104: suspending.
Scheduler: suspending 3075926960.
Scheduler: scheduling.
Scheduler: resuming 3065437104.
Thread 3065437104: resuming.
Thread 3075926960: suspending.
Scheduler: suspending 3065437104.
Thread 3065437104: leaving scheduler queue.
Scheduler: scheduling.
Scheduler: resuming 3075926960.
Thread 3075926960: resuming.
Thread 3065437104: terminating.
Thread 3054947248: in scheduler queue.
Thread 3054947248: suspending.
Scheduler: suspending 3075926960.
Thread 3075926960: leaving scheduler queue.
Scheduler: scheduling.
Scheduler: resuming 3054947248.
Thread 3054947248: resuming.
Thread 3075926960: terminating.
Scheduler: suspending 3054947248.
Scheduler: scheduling.
Scheduler: resuming 3054947248.
Thread 3054947248: suspending.
Thread 3054947248: resuming.
Scheduler: suspending 3054947248.
Scheduler: scheduling.
Scheduler: resuming 3054947248.
Thread 3054947248: suspending.
Thread 3054947248: resuming.
Scheduler: suspending 3054947248.
Thread 3054947248: leaving scheduler queue.
Thread 3054947248: terminating.
The total wait time is 12.062254 seconds.
The total run time is 7.958618 seconds.
The average wait time is 4.020751 seconds.
The average run time is 2.652873 seconds.
The goal of this MP is to help you understand (1) how signals
and timers work,
and (2) how to evaluate the performance of your program. You
will first
implement the time-sharing system using timers and signals.
Then, you will
evaluate the overall performance of your program by keeping
track of how long
each thread is idle, running, etc.
The program will use these four signals:
SIGALRM: sent by the timer to the scheduler, to indicate
another time
quantum has passed.
SIGUSR1: sent by the scheduler to a worker, to tell it to
suspend.
SIGUSR2: sent by the scheduler to a suspended worker, to tell
it to resume.
SIGTERM: sent by the scheduler to a worker, to tell it to
cancel.
You will need to set up the appropriate handlers and masks for
these signals.
You will use these functions:
clock_gettime
pthread_sigmask
pthread_kill
sigaction
sigaddset
sigemptyset
sigwait
timer_settime
timer_create
Also, make sure you understand how the POSIX:TMR interval
timer works.
There are two ways you can test your code. You can run the
built-in grading
tests by running "scheduler -test -f0 rr". This runs 5 tests, each
of which can
be run individually. You can also test you program with
specific parameters by
running "scheduler -test gen ..." where the ellipsis contains the
parameters you
would pass to scheduler.
Programming
===========
Part I: Modify the scheduler code (scheduler.c)
-----------------------------------------------
We use the scheduler thread to setup the timer and handle the
scheduling for the
system. The scheduler handles the SIGALRM events that come
from the timer, and
sends out signals to the worker threads.
Step 1.
Modify the code in init_sched_queue() function in scheduler.c
to initialize the
scheduler with a POSIX:TMR interval timer. Use
CLOCK_REALTIME in timer_create().
The timer will be stored in the global variable "timer", which
will be started
in scheduler_run() (see Step 4 below).
Step 2.
Implement setup_sig_handlers(). Use sigaction() to install
signal handlers for
SIGALRM, SIGUSR1, and SIGTERM. SIGALRM should
trigger timer_handler(), SIGUSR1
should trigger suspend_thread(), and SIGTERM should trigger
cancel_thread().
Notice no handler is installed for SIGUSR2; this signal will be
handled
differently, in step 8.
Step 3.
In the scheduler_run() function, start the timer. Use
timer_settime(). The
time quantum (1 second) is given in scheduler.h. The timer
should go off
repeatedly at regular intervals defined by the timer quantum.
In Round-Robin, whenever the timer goes off, the scheduler
suspends the
currently running thread, and tells the next thread to resume its
operations
using signals. These steps are listed in timer_handler(), which is
called every
time the timer goes off. In this implementation, the timer
handler makes use of
suspend_worker() and resume_worker() to accomplush these
steps.
Step 4.
Complete the suspend_worker() function. First, update the
info->quanta value.
This is the number of quanta that remain for this thread to
execute. It is
initialized to the value passed on the command line, and
decreases as the thread
executes. If there is any more work for this worker to do, send
it a signal to
suspend, and update the scheduler queue. Otherwise, cancel the
thread.
Step 5.
Complete the cancel_worker() function by sending the
appropriate signal to the
thread, telling it to kill itself.
Step 6.
Complete the resume_worker() function by sending the
appropriate signal to the
thread, telling it to resume execution.
Part II: Modify the worker code (worker.c)
------------------------------------------
In this section, you will modify the worker code to correctly
handle the signals
from the scheduler that you implemented in the previous
section.
You need to modify the thread functions so that it immediately
suspends the
thread, waiting for a resume signal from the scheduler. You will
need to use
sigwait() to force the thread to suspend itself and wait for a
resume signal.
You need also to implement a signal handler in worker.c to
catch and handle the
suspend signals.
Step 7.
Modify start_worker() to (1) block SIGUSR2 and SIGALRM,
and (2) unblock SIGUSR1
and SIGTERM.
Step 8.
Implement suspend_thread(), the handler for the SIGUSR1
signal. The
thread should block until it receives a resume (SIGUSR2)
signal.
Part III: Modify the evaluation code (scheduler.c)
--------------------------------------------------
This program keeps track of run time, and wait time. Each
thread saves these
two values regarding its own execution in its thread_info_t.
Tracking these
values requires also knowing the last time the thread suspended
or resumed.
Therefore, these two values are also kept in thread_info_t. See
scheduler.h.
In this section, you will implement the functions that calculate
run time and
wait time. All code that does this will be in scheduler.c. When
the program
is done, it will collect all these values, and print out the total
and average
wait time and run time. For your convenience, you are given a
function
time_difference() to compute the difference between two times
in microseconds.
Step 9.
Modify create_workers() to initialize the various time variables.
Step 10.
Implement update_run_time(). This is called by
suspend_worker().
Step 11.
Implement update_wait_time(). This is called by
resume_worker().
Questions
==========
Question 1.
Why do we block SIGUSR2 and SIGALRM in worker.c? Why
do we unblock SIGUSR1 and
SIGTERM in worker.c?
Question 2.
We use sigwait() and sigaction() in our code. Explain the
difference between the
two. (Please explain from the aspect of thread behavior rather
than syntax).
Question 3.
When we use POSIX:TMR interval timer, we are using relative
time. What is the
alternative? Explain the difference between the two.
Question 4.
Look at start_worker() in worker.c, a worker thread is executing
within an
infinite loop at the end. When does a worker thread terminate?
Question 5.
When does the scheduler finish? Why does it not exit when the
scheduler queue
is empty?
Question 6.
After a thread is scheduled to run, is it still in the sched_queue?
When is it
removed from the head of the queue? When is it removed from
the queue completely?
Question 7.
We've removed all other condition variables in SMP4, and
replaced them with a
timer and signals. Why do we still use the semaphore
queue_sem?
Question 8.
What's the purpose of the global variable "completed" in
scheduler.c? Why do we
compare "completed" with thread_count before we
wait_for_queue() in
next_worker()?
Question 9.
We only implemented Round Robin in this SMP. If we want to
implement a FIFO
scheduling algorithm and keep the modification as minimum,
which function in
scheduler.c is the one that you should modify? Briefly describe
how you would
modify this function.
Question 10.
In this implementation, the scheduler only changes threads
when the time quantum
expires. Briefly explain how you would use an additional signal
to allow the
scheduler to change threads in the middle of a time quantum. In
what situations
would this be useful?
__MACOSX/assign3/assign3_part2/._README.txt
assign3/assign3_part2/scheduler.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include "scheduler.h"
#include "worker.h"
/*
* define the extern global variables here.
*/
sem_t queue_sem; /* semaphore for scheduler queue
*/
thread_info_list sched_queue; /* list of current workers */
static int quit = 0;
static timer_t timer;
static thread_info_t *currentThread= 0;
static long wait_times;
static long run_times;
static int completed = 0;
static int thread_count = 0;
static void exit_error(int); /* helper function. */
static void wait_for_queue();
/****************************************************
***************************
*
* Implement these functions.
*
*****************************************************
*************************/
/*
* This function intializes the queue semaphore and the queue
itself.
*/
/*
* Update the worker's current running time.
* This function is called every time the thread is suspended.
*/
void update_run_time(thread_info_t *info) {
/* TODO: implement this function */
}
/*
* Update the worker's current waiting time.
* This function is called every time the thread resumes.
*/
void update_wait_time(thread_info_t *info) {
/* TODO: implement this function */
}
static void init_sched_queue(int queue_size)
{
/* set up a semaphore to restrict access to the queue */
sem_init(&queue_sem, 0, queue_size);
/* initialize the scheduler queue */
sched_queue.head = sched_queue.tail = 0;
pthread_mutex_init(&sched_queue.lock, NULL);
/* TODO: initialize the timer */
}
/*
* signal a worker thread that it can resume.
*/
static void resume_worker(thread_info_t *info)
{
printf("Scheduler: resuming %lu.n", info->thrid);
/*
* TODO: signal the worker thread that it can resume
*/
/* update the wait time for the thread */
update_wait_time(info);
}
/*send a signal to the thread, telling it to kill itself*/
void cancel_worker(thread_info_t *info)
{
/* TODO: send a signal to the thread, telling it to kill
itself*/
/* Update global wait and run time info */
wait_times += info->wait_time;
run_times += info->run_time;
completed++;
/* Update schedule queue */
leave_scheduler_queue(info);
if (completed >= thread_count) {
sched_yield(); /* Let other threads terminate. */
printf("The total wait time is %f seconds.n",
(float)wait_times / 1000000);
printf("The total run time is %f seconds.n",
(float)run_times / 1000000);
printf("The average wait time is %f seconds.n",
(float)wait_times / 1000000 / thread_count);
printf("The average run time is %f seconds.n",
(float)run_times / 1000000 / thread_count);
}
}
/*
* signals a worker thread that it should suspend.
*/
static void suspend_worker(thread_info_t *info)
{
int whatgoeshere = 0;
printf("Scheduler: suspending %lu.n", info->thrid);
/*update the run time for the thread*/
update_run_time(info);
/* TODO: Update quanta remaining. */
/* TODO: decide whether to cancel or suspend thread */
if(whatgoeshere) {
/*
* Thread still running: suspend.
* TODO: Signal the worker thread that it should
suspend.
*/
/* Update Schedule queue */
list_remove(&sched_queue,info->le);
list_insert_tail(&sched_queue,info->le);
} else {
/* Thread done: cancel */
cancel_worker(info);
}
}
/*
* this is the scheduling algorithm
* pick the next worker thread from the available list
* you may need to add new information to the thread_info
struct
*/
static thread_info_t *next_worker()
{
if (completed >= thread_count)
return 0;
wait_for_queue();
printf("Scheduler: scheduling.n");
/* return the thread_info_t for the next thread to run */
return sched_queue.head->info;
}
void timer_handler()
{
thread_info_t *info = 0;
/* once the last worker has been removed, we're done. */
if (list_size(&sched_queue) == 0) {
quit = 1;
return;
}
/*suspend the current worker*/
if (currentThread)
suspend_worker(currentThread);
//resume the next worker
info = next_worker();
/* Update currentThread */
currentThread = info;
if (info)
resume_worker(info);
else
quit = 1;
}
/*
* Set up the signal handlers for SIGALRM, SIGUSR1, and
SIGTERM.
* TODO: Implement this function.
*/
void setup_sig_handlers() {
/* Setup timer handler for SIGALRM signal in scheduler */
/* Setup cancel handler for SIGTERM signal in workers */
/* Setup suspend handler for SIGUSR1 signal in workers
*/
}
/****************************************************
***************************
*
*
*
*****************************************************
*************************/
/*
* waits until there are workers in the scheduling queue.
*/
static void wait_for_queue()
{
while(!list_size(&sched_queue)) {
printf("Scheduler: waiting for workers.n");
sched_yield();
}
}
/*
* runs at the end of the program just before exit.
*/
static void clean_up()
{
/*
* destroy any mutexes/condition variables/semaphores
that were created.
* free any malloc'd memory not already free'd
*/
sem_destroy(&queue_sem);
pthread_mutex_destroy(&sched_queue.lock);
}
/*
* prints the program help message.
*/
static void print_help(const char *progname)
{
printf("usage: %s <num_threads> <queue_size> <i_1, i_2
... i_numofthreads>n", progname);
printf("tnum_threads: the number of worker threads to
runn");
printf("tqueue_size: the number of threads that can be in
the scheduler at one timen");
printf("ti_1, i_2 ...i_numofthreads: the number of quanta
each worker thread runsn");
}
/*
* prints an error summary and exits.
*/
static void exit_error(int err_num)
{
fprintf(stderr, "failure: %sn", strerror(err_num));
exit(1);
}
/*
* creates the worker threads.
*/
static void create_workers(int thread_count, int *quanta)
{
int i = 0;
int err = 0;
for (i = 0; i < thread_count; i++) {
thread_info_t *info = (thread_info_t *)
malloc(sizeof(thread_info_t));
info->quanta = quanta[i];
if ((err = pthread_create(&info->thrid, NULL,
start_worker, (void *)info)) != 0) {
exit_error(err);
}
printf("Main: detaching worker thread %lu.n", info-
>thrid);
pthread_detach(info->thrid);
/* TODO: initialize the time variables for each thread
for performance evalution*/
}
}
/*
* runs the scheduler.
*/
static void *scheduler_run(void *unused)
{
wait_for_queue();
/* TODO: start the timer */
/*keep the scheduler thread alive*/
while( !quit )
sched_yield();
return NULL;
}
/*
* starts the scheduler.
* returns 0 on success or exits program on failure.
*/
static int start_scheduler(pthread_t *thrid)
{
int err = 0;
if ((err = pthread_create(thrid, NULL, scheduler_run, 0))
!= 0) {
exit_error(err);
}
return err;
}
/*
* reads the command line arguments and starts the scheduler &
worker threads.
*/
int smp5_main(int argc, const char** argv)
{
int queue_size = 0;
int ret_val = 0;
int *quanta,i;
pthread_t sched_thread;
/* check the arguments. */
if (argc < 3) {
print_help(argv[0]);
exit(0);
}
thread_count = atoi(argv[1]);
queue_size = atoi(argv[2]);
quanta = (int*)malloc(sizeof(int)*thread_count);
if (argc != 3 + thread_count) {
print_help(argv[0]);
exit(0);
}
for ( i = 0; i < thread_count; i++)
quanta[i] = atoi(argv[i+3]);
printf("Main: running %d workers with queue size %d for
quanta:n", thread_count, queue_size);
for ( i = 0; i < thread_count; i++)
printf(" %d", quanta[i]);
printf("n");
/*setup the sig handlers for scheduler and workers*/
setup_sig_handlers();
/* initialize anything that needs to be done for the
scheduler queue. */
init_sched_queue(queue_size);
/* creates a thread for the scheduler. */
start_scheduler(&sched_thread);
/* creates the worker threads and returns. */
create_workers(thread_count, quanta);
/* wait for scheduler to finish */
printf("Main: waiting for scheduler %lu.n",
sched_thread);
pthread_join(sched_thread, (void **) &ret_val);
/* clean up our resources */
clean_up();
/* this will wait for all other threads */
pthread_exit(0);
}
long time_difference(const struct timespec *time1, const struct
timespec *time2) {
return (time1->tv_sec - time2->tv_sec) * 1000000 +
(time1->tv_nsec - time2->tv_nsec) / 1000;
}
__MACOSX/assign3/assign3_part2/._scheduler.c
assign3/assign3_part2/testrunner.c
/*************** YOU SHOULD NOT MODIFY ANYTHING
IN THIS FILE ***************/
/*
A simple testrunner framework
Original Author: L. Angrave
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "testrunner.h"
/* Constants */
#define false (0)
#define true (1)
#define test_killed (2)
/* defaults */
static int default_timeout_seconds = 15;
static int timeout_seconds;
void set_testrunner_default_timeout(int s)
{
assert(s > 0);
default_timeout_seconds = s;
}
void set_testrunner_timeout(int s)
{
assert(s > 0);
timeout_seconds = s;
}
/* --- Helper macros and functions --- */
#define DIE(mesg)
{fprintf(stderr,"n%s(%d):%sn",__fname__,__LINE__,mesg);
exit(1);}
static int eql(const char *s1, const char *s2)
{
return s1 && s2 && !strcmp(s1, s2);
}
/* Callback function for qsort on strings */
static int mystrcmp(const void *p1, const void *p2)
{
return eql((const char *) p1, (const char *) p2);
}
/* Stats of all tests run so far */
typedef struct {
int ran, passed, failed;
} stats_t;
/* -- Signal handlers -- */
static pid_t child_pid;
static int sent_child_timeout_kill_signal;
static void kill_child_signal_handler(intsigno)
{
if (!child_pid)
return;
char m[] = "-Timeout(Killing test process)-";
write(0, m, sizeof(m) - 1);
kill(child_pid, SIGKILL);
sent_child_timeout_kill_signal = 1;
}
/* Internal function to run a test as a forked child. The child
process is terminated if it runs for more than a few seconds */
static int invoke_test_with_timelimit(testentry_t * test,
int redirect_stdouterr, int argc,
const char **argv)
{
char fname[255];
int wait_status;
pid_t wait_val;
struct sigaction action;
assert(!child_pid);
assert(test && test->test_function && test->name);
set_testrunner_timeout(default_timeout_seconds);
errno = 0;
child_pid = fork();
if (child_pid == -1) {
fprintf(stderr, "-fork failed so running test inline-");
return test->test_function(argc, argv);
}
if (child_pid == 0) {
if (redirect_stdouterr) {
snprintf(fname, (int) sizeof(fname), "stdout-%s.txt",
test->name);
fname[sizeof(fname) - 1] = 0;
freopen(fname, "w", stdout);
memcpy(fname + 3, "err", 3);
freopen(fname, "w", stderr);
}
exit(test->test_function(argc, argv));
} else {
wait_status = -1;
sigemptyset(&action.sa_mask);
action.sa_handler = kill_child_signal_handler;
sigaction(SIGALRM, &action, NULL);
sent_child_timeout_kill_signal = 0;
alarm(timeout_seconds);
wait_val = waitpid(child_pid, &wait_status, 0);
int child_exited_normally = WIFEXITED(wait_status);
int child_exit_value = WEXITSTATUS(wait_status);
int child_term_by_signal = WIFSIGNALED(wait_status);
int child_term_signal = WTERMSIG(wait_status);
if (child_term_by_signal) {
fprintf(stderr, "testrunner:Test terminated by signal
%dn",
child_term_signal);
fprintf(stderr,
"testrunner:waitpid returned %d
(child_pid=%d,wait_status=%d)",
wait_val, child_pid, wait_status);
}
if (child_pid != wait_val)
fprintf(stderr,
"testrunner: strange... wait_val != child_pidn");
int passed = (child_pid == wait_val) && (child_exit_value
== 0)
&& (child_exited_normally != 0);
alarm(0);
kill(child_pid, SIGKILL);
child_pid = 0;
return sent_child_timeout_kill_signal ? test_killed : passed
? 0 :
1;
}
}
/*
* run a test and update the stats. The main guts of this
functionality is provided by invoke_test_with_timelimit
* This outer wrapper updates thes output and statistics before
and after running the test.
*/
static int
run_one_test(stats_t * stats, testentry_t * test, int
redirect_stdouterr,
int argc, const char **argv)
{
int test_result;
assert(stats && test->name && argc > 0 && argv && *argv);
stats->ran++;
stats->failed++;
printf("%2d.%-20s:", stats->ran, test->name);
fflush(stdout);
test_result =
invoke_test_with_timelimit(test, redirect_stdouterr, argc,
argv);
if (test_result == 0) {
stats->failed--;
stats->passed++;
}
printf(":%sn", (test_result == 0 ? "pass" : test_result ==
2 ? "TIMEOUT * " : "FAIL *"));
return test_result != 0;
}
/* Help functionality to print out sorted list of test names and
suite names */
static void print_targets(testentry_t tests[], int count)
{
const char **array;
const char *previous;
int i;
array = (const char **) calloc(sizeof(const char *), count);
/* Sort the test names and print unique entries */
for (i = 0; i < count; i++)
array[i] = tests[i].name;
qsort(array, count, sizeof(array[0]), mystrcmp);
printf("nValid tests : all");
for (i = 0, previous = ""; i < count; i++)
if (!eql(previous, array[i]))
printf(" %s", (previous = array[i]));
/* Sort the suite names and print unique entries */
for (i = 0; i < count; i++)
array[i] = tests[i].suite;
qsort(array, count, sizeof(array[0]), mystrcmp);
printf("nValid suites:");
for (i = 0, previous = ""; i < count; i++)
if (!eql(previous, array[i]))
printf(" %s", (previous = array[i]));
printf("n");
}
/*
* Main entry point for test harness
*/
int
run_testrunner(int argc, const char **argv, testentry_t tests[],
int test_count)
{
const char *test_name, *target;
int i;
stats_t stats;
int target_matched, max_errors_before_quit,
redirect_stdouterr;
memset(&stats, 0, sizeof(stats));
max_errors_before_quit = 1;
redirect_stdouterr = 0;
assert(tests != NULL);
assert(test_count > 0);
assert(argc > 0 && argv && *argv);
while (true) {
target = argc > 1 ? argv[1] : "";
assert(target);
if (*target != '-')
break;
argc--;
argv++;
if (target[1] == 'f' && target[2])
max_errors_before_quit = atoi(target + 1);
else if (target[1] == 'r')
redirect_stdouterr = 1;
}
target_matched = false;
for (i = 0;
i < test_count && (max_errors_before_quit < 1
|| stats.failed != max_errors_before_quit);
i++) {
test_name = tests[i].name;
assert(test_name);
assert(tests[i].suite);
assert(tests[i].test_function);
if (eql(target, test_name) || eql(target, "all")
|| eql(target, tests[i].suite)) {
if (!target_matched)
printf("Running tests...n");
target_matched = true;
run_one_test(&stats, &tests[i], redirect_stdouterr, argc -
1,
argv + 1);
}
}
if (!target_matched) {
fprintf(stderr, "Test '%s' not found",
(strlen(target) > 0 ? target : "(empty)"));
print_targets(tests, test_count);
} else {
printf("nTest Results:%d tests,%d passed,%d failed.n",
stats.ran,
stats.passed, stats.failed);
}
return stats.passed == stats.ran && target_matched ? 0 : 1;
}
__MACOSX/assign3/assign3_part2/._testrunner.c
“Social Change”
Program Transcript
HOLLY HOEY: So Maurice, as we talk about social change, I
know there's a
story behind how you got into this field. I can just sense your
passion and
enthusiasm for what you do.
MAURICE WILLIAMS: Well, I've always had an interest in the
human condition.
My undergrad was in psychology, so we studied a lot about the
mind, human
behavior. I've always been inquisitive. I want to know; how did
we get here, who
are we, why are we so different, why are we so alike, what
makes us who we
are? And so, literally, that's why I got into it.
Now, as I started working in the field though, I saw that, wow,
it's not about
being inquisitive. There's really a lot of needs out here for
people. There's a lot
of pain out here. It's a lot of trauma, a lot of grief, a lot of loss.
And I come from
a family that has always been very community focused.
And so I got into working with people with disabilities. And
then next, I worked
with adults who were on assistance, tenants assistance. And
then I ended up
working with children. And now it's like, "Wow, there it is."
Children have such a
vulnerability, but such a purity. I can connect with them,
because children always
remind me that we all were one of them at one time. And I'm
fortunate enough to
have gotten into a field that keeps me focused on, like Holly
asked, What am I
going to do good today? Who am I going to help? Not really
save, but who am I
going to help progress further in their life."
HOLLY HOEY: What about you Andrea?
ANDREA INGRAM: Well, I grew up in a large family, a lot of
kids, and I was in
the middle. So middle children, we do a lot of mediating and all
this kind of stuff.
But, I also grew up with a very keen sense of justice and
fairness. When there
are seven kids in the family, you learn that life is not fair. And
my parents had a
strong sense of justice also, and
were great examples.
So when I went out into the world, I felt an obligation, a
responsibility to try to
make life better for people that didn't have it as well as I did.
Because to me, it's a
sense of justice and fairness to include people in the mainstream
who are left out,
for whatever reason. They're left out because of poverty, they're
left out because
of mental illness, or there are left out because of their
personality. They're just left
out because of relationships.
So it's just because of, I think, being raised with a keen sense of
fairness and
justice and wanting to have an impact on that.
I found that I really loved crisis work, because when people are
in crisis there's
such energy there and motivation to make things different. And
there's a real
opportunity to make things different and to make some really
significant changes
and reach some really significant resolutions in your life that
really might put you
on a different path.
HOLLY HOEY: I say that I'm in this field by default. But it
worked out to my
benefit, because I absolutely love what I do. I wasn't a middle
child, but I've
always been a mediator. Always. "Are you OK? Is everyone
OK? Let's make sure
everybody gets along." And so that's just my personality.
But I have a degree in interior design. And so I did design work
for five years.
And I race walked a marathon for Leukemia Society, and we
had to raise money.
Here we go. Here goes my life story. And I had to raise money,
which I found to
be so simple. And people kept saying, "How are you raising all
that money?" And
I said, "It's because I believe in it." If I could talk about it and I
believed in it, and I
really had a case for why I was raising money, I found it to be
very easy.
And so here goes my career change. I loved it. And I said, "I'm
not fulfilled in
my previous job." And I just said, "I'm going to make a life
change." And it
was the best change that I made. And 12 years later, here I am. I
love it at
United Way.
And I just feel that I connect the dots. That's my job. I connect
the dots. I
connect the dots with my volunteers, with donors, to people that
need help. And
United Way does the same thing with partners. And I just feel
that that's where
my skill set is. If I can bring these people together to effect
change, I've done
my job.
So we're talking about how our organizations influence social
change. And I
think this is actually the most exciting part to discuss, because
being at United
Way for over 12 years, I think that my job every day is
extremely rewarding and
fulfilling.
What United Way of Central Maryland does is to again,
mobilize the community
to improve people's lives. We are touching the lives and
changing lives as it
relates to helping people sustain their lives, to stabilize, and
then getting them
out of that spiraling poverty and getting them to self-
sufficiency. My job is to
educate and communicate and inform individuals about the most
pressing
needs in this community.
MAURICE WILLIAMS: I, like you, Holly, believe that social
change is very, very
important for our organization as well, the Williams Life
Center. We service
people who are born into the number one institution, the first
institution that
they'll ever be a part of, which is the family. Unfortunately,
their families fall apart
for whatever reasons, neglect, abuse, drugs, incarceration. Some
families and
some parents want to take care of the kids, but they just don't
have the
resources and the capabilities to do so. And so we at the
Williams Life Center
bring them in.
Some children come into our program and they've already lost a
lot. And maybe
they're now 14 already when they come into the system, and
some of them have
a long way to go. And they may falter and they may not be
successful in the
program that we provide to them. But then there are others,
which far outweigh
the ones that don't make it, that will come in and although they
have the
emotional baggage that they have, and the traumas that they've
experienced, we
watch them grow and we watch them become connected to a
family.
And that is so rewarding, because we see that as our duty to
ensure that these
children, no matter what their previous life would have been
like, that when they
come to our agency we're going to take care of them, bottom
line. We're going to
take care of them. And if they're in an environment that is not
meeting the
standard, we move them. And then those that aren't meeting the
standard, but we
can work with them to get them higher, we do that. And so
that's how we believe
we affect social change. Because this is another child who may
not grow up to be
an abuser himself.
ANDREA INGRAM: Well, to me, social change is very
personal. You talked
about volunteers. You talked about your families and the kids. I
think large
change starts with one person, and it goes from that person to
their family, to
their congregation.
An example that I would like to talk a little bit about is, we do a
lot of services for
people with mental illness. And they're in our shelter programs,
but we also have
a mobile crisis team and we go out with the police. We also do
some training with
the Police Department on how to better manage situations with a
person who's
perhaps having a psychotic episode, may be behaviorally out of
control, resulting
in some family conflict, and so forth.
There's one person that we respond to all the time. When she's
not in treatment,
it can be pretty outrageous, including challenging the police,
very confrontational.
It could even be sexually oriented. When the police went to
lunch at this day
program, there she was. And it was at a point in her life where
she was in
treatment. And the police were just amazed. They sat down with
her, were able to
talk with her, see her when she is in treatment and is doing
well. And were even
able to talk to her about, how should we behave when we come
out and you're in
crisis? So that she could even have some input into how the
police and the
mobile crisis team would respond to her.
That one thing transfers to other police officers, transfers to
how they act when
they respond to other people who are having a mental health
crisis. Because they
can see the person behind the crisis. And when you see the
person behind the
crisis, you handle it a little differently. So that to me is social
change, one person
at a time.
MAURICE WILLIAMS: When we think of social change,
sometimes I think we
think of somebody standing behind a podium saying, "Let's do
it," and there's
hundreds of thousands of people out there on the lawn listening.
But it's really
one person at a time.
And sometimes, in our jobs, we have to remind ourselves how
important
what we do really is.
I was in Walmart two weeks ago, and a foster family came up to
me and said,
"Hey, Mr. Williams." And I turned around and it was a 16-year
old who I had
placed there over a year ago with her foster mother. And the 16-
year old has a
son who was born about a year or so ago. The son was born with
extreme
health needs. And so working with this child, she broke down.
She said, "I'm in
twelfth grade. My child is sick." The child was in the hospital
for like three
months at a time. And we said to her, "We will help you through
this. We're
going to ensure that you graduate. We're going to ensure that
this baby is
taken care of." And we stuck with her.
And so when I walked away after we spoke, I looked back at
them again and I
said to myself, "Wow, that could have never happened had we
not really
worked to keep this girl together, to keep this baby together, to
keep this
family together." So sometimes, little glimpses will come that
says, "You know
what Maurice, what you guys do is really important."
And so it is one individual at a time. It really is.
© 2013 Laureate Education, Inc. 4

More Related Content

More from rosemariebrayshaw

Southwestern Business Administration JournalVolume 16 Is.docx
Southwestern Business Administration JournalVolume 16  Is.docxSouthwestern Business Administration JournalVolume 16  Is.docx
Southwestern Business Administration JournalVolume 16 Is.docxrosemariebrayshaw
 
Spadoni • revised Jan. 2020 —continued— Checklist for .docx
Spadoni • revised Jan. 2020 —continued— Checklist for .docxSpadoni • revised Jan. 2020 —continued— Checklist for .docx
Spadoni • revised Jan. 2020 —continued— Checklist for .docxrosemariebrayshaw
 
SPAN100Course SummaryCourse SPAN100 Title Spanish I.docx
SPAN100Course SummaryCourse  SPAN100 Title  Spanish I.docxSPAN100Course SummaryCourse  SPAN100 Title  Spanish I.docx
SPAN100Course SummaryCourse SPAN100 Title Spanish I.docxrosemariebrayshaw
 
Sources and Resources for RC004Informed Advocacy in Early .docx
Sources and Resources for RC004Informed Advocacy in Early .docxSources and Resources for RC004Informed Advocacy in Early .docx
Sources and Resources for RC004Informed Advocacy in Early .docxrosemariebrayshaw
 
Sources of General Information about the Topic A paragr.docx
Sources of General Information about the Topic  A paragr.docxSources of General Information about the Topic  A paragr.docx
Sources of General Information about the Topic A paragr.docxrosemariebrayshaw
 
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docx
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docxSouthside Community Services Mrs. Bargas Case History© 2018 Lau.docx
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docxrosemariebrayshaw
 
Sources and Tips for Assignment 1 (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 1  (History 105; Prof. Stansbury)—.docxSources and Tips for Assignment 1  (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 1 (History 105; Prof. Stansbury)—.docxrosemariebrayshaw
 
Source for ArticleMilliken, A. (2018). Ethical awareness What .docx
Source for ArticleMilliken, A. (2018). Ethical awareness What .docxSource for ArticleMilliken, A. (2018). Ethical awareness What .docx
Source for ArticleMilliken, A. (2018). Ethical awareness What .docxrosemariebrayshaw
 
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docx
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docxSoria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docx
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docxrosemariebrayshaw
 
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docx
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docxSPC1017 Rubric Informative SpeechName JhoanSpeech Top.docx
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docxrosemariebrayshaw
 
South University College of Nursing and Public Health Graduate.docx
South University College of Nursing and Public Health Graduate.docxSouth University College of Nursing and Public Health Graduate.docx
South University College of Nursing and Public Health Graduate.docxrosemariebrayshaw
 
Sources to UseSuskie, L. (2014, March 17). What is good.docx
Sources to UseSuskie, L. (2014, March 17). What is good.docxSources to UseSuskie, L. (2014, March 17). What is good.docx
Sources to UseSuskie, L. (2014, March 17). What is good.docxrosemariebrayshaw
 
Sooner or later you’ll find your-self leading a team where one.docx
Sooner or later you’ll find your-self leading a team where one.docxSooner or later you’ll find your-self leading a team where one.docx
Sooner or later you’ll find your-self leading a team where one.docxrosemariebrayshaw
 
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docx
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docxSophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docx
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docxrosemariebrayshaw
 
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docx
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docxSoria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docx
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docxrosemariebrayshaw
 
Sources and Tips for Assignment 3 (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 3  (History 105; Prof. Stansbury)—.docxSources and Tips for Assignment 3  (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 3 (History 105; Prof. Stansbury)—.docxrosemariebrayshaw
 
Some of the bibliography docsKarls Marxhttpswww.marxi.docx
Some of the bibliography docsKarls Marxhttpswww.marxi.docxSome of the bibliography docsKarls Marxhttpswww.marxi.docx
Some of the bibliography docsKarls Marxhttpswww.marxi.docxrosemariebrayshaw
 
Sources of Risk for Chronic Conditions in the State of Flo.docx
Sources of Risk for Chronic Conditions in the State of Flo.docxSources of Risk for Chronic Conditions in the State of Flo.docx
Sources of Risk for Chronic Conditions in the State of Flo.docxrosemariebrayshaw
 
Source Shutterstock.com .docx
Source Shutterstock.com .docxSource Shutterstock.com .docx
Source Shutterstock.com .docxrosemariebrayshaw
 
SolarComm Communication and Collaboration Team BiographiesName.docx
SolarComm Communication and Collaboration Team BiographiesName.docxSolarComm Communication and Collaboration Team BiographiesName.docx
SolarComm Communication and Collaboration Team BiographiesName.docxrosemariebrayshaw
 

More from rosemariebrayshaw (20)

Southwestern Business Administration JournalVolume 16 Is.docx
Southwestern Business Administration JournalVolume 16  Is.docxSouthwestern Business Administration JournalVolume 16  Is.docx
Southwestern Business Administration JournalVolume 16 Is.docx
 
Spadoni • revised Jan. 2020 —continued— Checklist for .docx
Spadoni • revised Jan. 2020 —continued— Checklist for .docxSpadoni • revised Jan. 2020 —continued— Checklist for .docx
Spadoni • revised Jan. 2020 —continued— Checklist for .docx
 
SPAN100Course SummaryCourse SPAN100 Title Spanish I.docx
SPAN100Course SummaryCourse  SPAN100 Title  Spanish I.docxSPAN100Course SummaryCourse  SPAN100 Title  Spanish I.docx
SPAN100Course SummaryCourse SPAN100 Title Spanish I.docx
 
Sources and Resources for RC004Informed Advocacy in Early .docx
Sources and Resources for RC004Informed Advocacy in Early .docxSources and Resources for RC004Informed Advocacy in Early .docx
Sources and Resources for RC004Informed Advocacy in Early .docx
 
Sources of General Information about the Topic A paragr.docx
Sources of General Information about the Topic  A paragr.docxSources of General Information about the Topic  A paragr.docx
Sources of General Information about the Topic A paragr.docx
 
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docx
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docxSouthside Community Services Mrs. Bargas Case History© 2018 Lau.docx
Southside Community Services Mrs. Bargas Case History© 2018 Lau.docx
 
Sources and Tips for Assignment 1 (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 1  (History 105; Prof. Stansbury)—.docxSources and Tips for Assignment 1  (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 1 (History 105; Prof. Stansbury)—.docx
 
Source for ArticleMilliken, A. (2018). Ethical awareness What .docx
Source for ArticleMilliken, A. (2018). Ethical awareness What .docxSource for ArticleMilliken, A. (2018). Ethical awareness What .docx
Source for ArticleMilliken, A. (2018). Ethical awareness What .docx
 
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docx
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docxSoria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docx
Soria 2Victoria SoriaDean WintherEnglish 101 10 March 20.docx
 
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docx
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docxSPC1017 Rubric Informative SpeechName JhoanSpeech Top.docx
SPC1017 Rubric Informative SpeechName JhoanSpeech Top.docx
 
South University College of Nursing and Public Health Graduate.docx
South University College of Nursing and Public Health Graduate.docxSouth University College of Nursing and Public Health Graduate.docx
South University College of Nursing and Public Health Graduate.docx
 
Sources to UseSuskie, L. (2014, March 17). What is good.docx
Sources to UseSuskie, L. (2014, March 17). What is good.docxSources to UseSuskie, L. (2014, March 17). What is good.docx
Sources to UseSuskie, L. (2014, March 17). What is good.docx
 
Sooner or later you’ll find your-self leading a team where one.docx
Sooner or later you’ll find your-self leading a team where one.docxSooner or later you’ll find your-self leading a team where one.docx
Sooner or later you’ll find your-self leading a team where one.docx
 
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docx
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docxSophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docx
Sophia Bosoni, Tombra Esite & Junhui LiuFebruary 6, 2020 Innov.docx
 
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docx
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docxSoria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docx
Soria 2Victoria Soria Dean WintherEnglish 101 04 Februar.docx
 
Sources and Tips for Assignment 3 (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 3  (History 105; Prof. Stansbury)—.docxSources and Tips for Assignment 3  (History 105; Prof. Stansbury)—.docx
Sources and Tips for Assignment 3 (History 105; Prof. Stansbury)—.docx
 
Some of the bibliography docsKarls Marxhttpswww.marxi.docx
Some of the bibliography docsKarls Marxhttpswww.marxi.docxSome of the bibliography docsKarls Marxhttpswww.marxi.docx
Some of the bibliography docsKarls Marxhttpswww.marxi.docx
 
Sources of Risk for Chronic Conditions in the State of Flo.docx
Sources of Risk for Chronic Conditions in the State of Flo.docxSources of Risk for Chronic Conditions in the State of Flo.docx
Sources of Risk for Chronic Conditions in the State of Flo.docx
 
Source Shutterstock.com .docx
Source Shutterstock.com .docxSource Shutterstock.com .docx
Source Shutterstock.com .docx
 
SolarComm Communication and Collaboration Team BiographiesName.docx
SolarComm Communication and Collaboration Team BiographiesName.docxSolarComm Communication and Collaboration Team BiographiesName.docx
SolarComm Communication and Collaboration Team BiographiesName.docx
 

Recently uploaded

Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxthorishapillay1
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxUnboundStockton
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17Celine George
 
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,Virag Sontakke
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptxVS Mahajan Coaching Centre
 
Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfMahmoud M. Sallam
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application ) Sakshi Ghasle
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Educationpboyjonauth
 
Painted Grey Ware.pptx, PGW Culture of India
Painted Grey Ware.pptx, PGW Culture of IndiaPainted Grey Ware.pptx, PGW Culture of India
Painted Grey Ware.pptx, PGW Culture of IndiaVirag Sontakke
 
Biting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfBiting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfadityarao40181
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonJericReyAuditor
 
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfEnzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfSumit Tiwari
 
The Most Excellent Way | 1 Corinthians 13
The Most Excellent Way | 1 Corinthians 13The Most Excellent Way | 1 Corinthians 13
The Most Excellent Way | 1 Corinthians 13Steve Thomason
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformChameera Dedduwage
 
internship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerinternship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerunnathinaik
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxGaneshChakor2
 

Recently uploaded (20)

Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptx
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docx
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17
 
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
 
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
 
Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdf
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application )
 
Introduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher EducationIntroduction to ArtificiaI Intelligence in Higher Education
Introduction to ArtificiaI Intelligence in Higher Education
 
Painted Grey Ware.pptx, PGW Culture of India
Painted Grey Ware.pptx, PGW Culture of IndiaPainted Grey Ware.pptx, PGW Culture of India
Painted Grey Ware.pptx, PGW Culture of India
 
Biting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfBiting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdf
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lesson
 
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
 
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
call girls in Kamla Market (DELHI) 🔝 >༒9953330565🔝 genuine Escort Service 🔝✔️✔️
 
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfEnzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
 
The Most Excellent Way | 1 Corinthians 13
The Most Excellent Way | 1 Corinthians 13The Most Excellent Way | 1 Corinthians 13
The Most Excellent Way | 1 Corinthians 13
 
A Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy ReformA Critique of the Proposed National Education Policy Reform
A Critique of the Proposed National Education Policy Reform
 
internship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerinternship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developer
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptx
 

Social Change”Pro.docx

  • 1. “Social Change” Program Transcript HOLLY HOEY: So Maurice, as we talk about social change, I know there's a story behind how you got into this field. I can just sense your passion and enthusiasm for what you do. MAURICE WILLIAMS: Well, I've always had an interest in the human condition.
  • 2. My undergrad was in psychology, so we studied a lot about the mind, human behavior. I've always been inquisitive. I want to know; how did we get here, who are we, why are we so different, why are we so alike, what makes us who we are? And so, literally, that's why I got into it. Now, as I started working in the field though, I saw that, wow, it's not about being inquisitive. There's really a lot of needs out here for people. There's a lot of pain out here. It's a lot of trauma, a lot of grief, a lot of loss. And I come from a family that has always been very community focused. And so I got into working with people with disabilities. And then next, I worked with adults who were on assistance, tenants assistance. And then I ended up working with children. And now it's like, "Wow, there it is." Children have such a vulnerability, but such a purity. I can connect with them, because children always remind me that we all were one of them at one time. And I'm fortunate enough to have gotten into a field that keeps me focused on, like Holly asked, What am I going to do good today? Who am I going to help? Not really save, but who am I going to help progress further in their life." HOLLY HOEY: What about you Andrea? ANDREA INGRAM: Well, I grew up in a large family, a lot of kids, and I was in
  • 3. the middle. So middle children, we do a lot of mediating and all this kind of stuff. But, I also grew up with a very keen sense of justice and fairness. When there are seven kids in the family, you learn that life is not fair. And my parents had a strong sense of justice also, and were great examples. So when I went out into the world, I felt an obligation, a responsibility to try to make life better for people that didn't have it as well as I did. Because to me, it's a sense of justice and fairness to include people in the mainstream who are left out, for whatever reason. They're left out because of poverty, they're left out because of mental illness, or there are left out because of their personality. They're just left out because of relationships. So it's just because of, I think, being raised with a keen sense of fairness and justice and wanting to have an impact on that.
  • 4. I found that I really loved crisis work, because when people are in crisis there's such energy there and motivation to make things different. And there's a real opportunity to make things different and to make some really significant changes and reach some really significant resolutions in your life that really might put you on a different path. HOLLY HOEY: I say that I'm in this field by default. But it worked out to my benefit, because I absolutely love what I do. I wasn't a middle child, but I've always been a mediator. Always. "Are you OK? Is everyone OK? Let's make sure everybody gets along." And so that's just my personality. But I have a degree in interior design. And so I did design work for five years. And I race walked a marathon for Leukemia Society, and we had to raise money. Here we go. Here goes my life story. And I had to raise money,
  • 5. which I found to be so simple. And people kept saying, "How are you raising all that money?" And I said, "It's because I believe in it." If I could talk about it and I believed in it, and I really had a case for why I was raising money, I found it to be very easy. And so here goes my career change. I loved it. And I said, "I'm not fulfilled in my previous job." And I just said, "I'm going to make a life change." And it was the best change that I made. And 12 years later, here I am. I love it at United Way. And I just feel that I connect the dots. That's my job. I connect the dots. I connect the dots with my volunteers, with donors, to people that need help. And United Way does the same thing with partners. And I just feel that that's where my skill set is. If I can bring these people together to effect change, I've done my job. So we're talking about how our organizations influence social change. And I think this is actually the most exciting part to discuss, because being at United Way for over 12 years, I think that my job every day is extremely rewarding and fulfilling. What United Way of Central Maryland does is to again, mobilize the community
  • 6. to improve people's lives. We are touching the lives and changing lives as it relates to helping people sustain their lives, to stabilize, and then getting them out of that spiraling poverty and getting them to self- sufficiency. My job is to educate and communicate and inform individuals about the most pressing needs in this community. MAURICE WILLIAMS: I, like you, Holly, believe that social change is very, very important for our organization as well, the Williams Life Center. We service people who are born into the number one institution, the first institution that they'll ever be a part of, which is the family. Unfortunately, their families fall apart for whatever reasons, neglect, abuse, drugs, incarceration. Some families and some parents want to take care of the kids, but they just don't have the resources and the capabilities to do so. And so we at the Williams Life Center bring them in.
  • 7. Some children come into our program and they've already lost a lot. And maybe they're now 14 already when they come into the system, and some of them have a long way to go. And they may falter and they may not be successful in the program that we provide to them. But then there are others, which far outweigh the ones that don't make it, that will come in and although they have the emotional baggage that they have, and the traumas that they've experienced, we watch them grow and we watch them become connected to a family. And that is so rewarding, because we see that as our duty to ensure that these children, no matter what their previous life would have been like, that when they
  • 8. come to our agency we're going to take care of them, bottom line. We're going to take care of them. And if they're in an environment that is not meeting the standard, we move them. And then those that aren't meeting the standard, but we can work with them to get them higher, we do that. And so that's how we believe we affect social change. Because this is another child who may not grow up to be an abuser himself. ANDREA INGRAM: Well, to me, social change is very personal. You talked about volunteers. You talked about your families and the kids. I think large change starts with one person, and it goes from that person to their family, to their congregation. An example that I would like to talk a little bit about is, we do a lot of services for people with mental illness. And they're in our shelter programs, but we also have a mobile crisis team and we go out with the police. We also do some training with the Police Department on how to better manage situations with a person who's perhaps having a psychotic episode, may be behaviorally out of control, resulting in some family conflict, and so forth. There's one person that we respond to all the time. When she's not in treatment, it can be pretty outrageous, including challenging the police, very confrontational.
  • 9. It could even be sexually oriented. When the police went to lunch at this day program, there she was. And it was at a point in her life where she was in treatment. And the police were just amazed. They sat down with her, were able to talk with her, see her when she is in treatment and is doing well. And were even able to talk to her about, how should we behave when we come out and you're in crisis? So that she could even have some input into how the police and the mobile crisis team would respond to her. That one thing transfers to other police officers, transfers to how they act when they respond to other people who are having a mental health crisis. Because they can see the person behind the crisis. And when you see the person behind the crisis, you handle it a little differently. So that to me is social change, one person at a time. MAURICE WILLIAMS: When we think of social change, sometimes I think we think of somebody standing behind a podium saying, "Let's do it," and there's hundreds of thousands of people out there on the lawn listening. But it's really one person at a time.
  • 10. And sometimes, in our jobs, we have to remind ourselves how important what we do really is. I was in Walmart two weeks ago, and a foster family came up to me and said, "Hey, Mr. Williams." And I turned around and it was a 16-year old who I had placed there over a year ago with her foster mother. And the 16- year old has a son who was born about a year or so ago. The son was born with extreme health needs. And so working with this child, she broke down. She said, "I'm in twelfth grade. My child is sick." The child was in the hospital for like three months at a time. And we said to her, "We will help you through this. We're going to ensure that you graduate. We're going to ensure that this baby is taken care of." And we stuck with her. And so when I walked away after we spoke, I looked back at them again and I said to myself, "Wow, that could have never happened had we not really
  • 11. worked to keep this girl together, to keep this baby together, to keep this family together." So sometimes, little glimpses will come that says, "You know what Maurice, what you guys do is really important." And so it is one individual at a time. It really is. © 2013 Laureate Education, Inc. 4 __MACOSX/._assign3 assign3/.DS_Store __MACOSX/assign3/._.DS_Store assign3/assign3_part2/list.c #include <stdio.h> #include "list.h" /* list helper functions */ int list_size(thread_info_list *list) { int cnt = 0; if (!list) return -1; pthread_mutex_lock(&list->lock); list_elem *le = list->head; while (le) { cnt++; le = le->next; }
  • 12. pthread_mutex_unlock(&list->lock); return cnt; } int list_insert_head(thread_info_list *list, list_elem *new) { if (!list || !new) return -1; pthread_mutex_lock(&list->lock); new->next = list->head; new->prev = 0; if (new->next) { new->next->prev = new; } list->head = new; if (list->tail == 0) { list->tail = new; } pthread_mutex_unlock(&list->lock); return 0; } int list_insert_tail(thread_info_list *list, list_elem *new) { if (!list || !new) return -1; pthread_mutex_lock(&list->lock); new->prev = list->tail; new->next = 0; if (new->prev) { new->prev->next = new; } list->tail = new; if (list->head == 0) {
  • 13. list->head = new; } pthread_mutex_unlock(&list->lock); return 0; } int list_remove(thread_info_list *list, list_elem *old) { if (!old || !list) return -1; pthread_mutex_lock(&list->lock); if (old->next) { old->next->prev = old->prev; } if (old->prev) { old->prev->next = old->next; } if (list->tail == old) { list->tail = old->prev; } if (list->head == old) { list->head = old->next; } old->next = old->prev = 0; pthread_mutex_unlock(&list->lock); return 0; } void print_list(thread_info_list *list) { pthread_mutex_lock(&list->lock); list_elem *le = list->head; while (le) {
  • 14. printf("0x%X,", (unsigned int)le->info); le = le->next; } pthread_mutex_unlock(&list->lock); printf("n"); } __MACOSX/assign3/assign3_part2/._list.c assign3/assign3_part2/worker.c #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include "scheduler.h" /**************************************************** *************************** * * Implement these functions. * ***************************************************** *************************/ /* Handler for SIGTERM signal */ void cancel_thread() { printf("Thread %u: terminating.n", (unsigned int)pthread_self()); /* signal that done in queue */
  • 15. sem_post(&queue_sem); pthread_exit(NULL); } /* TODO: Handle the SIGUSR1 signal */ void suspend_thread() { printf("Thread %u: suspending.n", (unsigned int)pthread_self()); /*add your code here to wait for a resume signal from the scheduler*/ printf("Thread %u: resuming.n",(unsigned int) pthread_self()); } /**************************************************** *************************** * * * ***************************************************** *************************/ /* * waits to gain access to the scheduler queue. */ static int enter_scheduler_queue(thread_info_t *info) { /* * wait for available room in queue. * create a new list entry for this thread * store this thread info in the new entry. */
  • 16. sem_wait(&queue_sem); list_elem *item = (list_elem*)malloc(sizeof(list_elem)); info->le = item; item->info = info; item->prev = 0; item->next = 0; list_insert_tail(&sched_queue, item); return 0; } /* * leaves the scheduler queue */ void leave_scheduler_queue(thread_info_t *info) { printf("Thread %lu: leaving scheduler queue.n", info- >thrid); /* * remove the given worker from queue * clean up the memory that we malloc'd for the list * clean up the memory that was passed to us */ list_remove(&sched_queue, info->le); free(info->le); free(info); } /* * Initialize thread, enter scheduling queue, and execute instructions. * arg is a pointer to thread_info_t */ void *start_worker(void *arg) { thread_info_t *info = (thread_info_t *) arg;
  • 17. float calc = 0.8; int j = 0; /* TODO: Block SIGALRM and SIGUSR2. */ /* TODO: Unblock SIGUSR1 and SIGTERM. */ /* compete with other threads to enter queue. */ if (enter_scheduler_queue(info)) { printf("Thread %lu: failure entering scheduler queue - %sn", info->thrid, strerror(errno)); free (info); pthread_exit(0); } printf("Thread %lu: in scheduler queue.n", info->thrid); suspend_thread(); while (1) { /* do some meaningless work... */ for (j = 0; j < 10000000; j++) { calc = 4.0 * calc * (1.0 - calc); } } } __MACOSX/assign3/assign3_part2/._worker.c assign3/assign3_part2/Makefile CC = gcc CCOPTS = -c -g -Wall LINKOPTS = -g -pthread -Wall EXEC=scheduler
  • 18. OBJECTS=scheduler.o worker.o list.o smp5_tests.o testrunner.o all: $(EXEC) $(EXEC): $(OBJECTS) $(CC) $(LINKOPTS) -o [email protected] $^ -lrt %.o:%.c $(CC) $(CCOPTS) -o [email protected] $^ clean: - $(RM) $(EXEC) - $(RM) $(OBJECTS) - $(RM) *~ - $(RM) core.* test: scheduler - ./scheduler -test -f0 rr - killall -q -KILL scheduler; true pretty: indent *.c *.h -kr __MACOSX/assign3/assign3_part2/._Makefile assign3/assign3_part2/scheduler.h #ifndef __SCHEDULER_H_ #define __SCHEDULER_H_ #include <pthread.h> #include <semaphore.h> #include "list.h" #define QUANTUM 1
  • 19. /* typedefs */ typedef struct thread_info { pthread_t thrid; int quanta; list_elem* le; /*added for evalution bookkeeping*/ struct timespec suspend_time; struct timespec resume_time; long wait_time; long run_time; } thread_info_t; /* functions */ void *start_worker(void *); long time_difference(const struct timespec*, const struct timespec*); int smp5_main(int argc, const char** argv); /* shared variables */ extern sem_t queue_sem; /* semaphore for scheduler queue */ extern thread_info_list sched_queue; /* list of current workers */ #endif /* __SCHEDULER_H_ */ __MACOSX/assign3/assign3_part2/._scheduler.h assign3/assign3_part2/smp5_tests.c /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ #define _GNU_SOURCE #include <stdio.h> #undef _GNU_SOURCE #include <stdlib.h>
  • 20. #include <string.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #include "testrunner.h" #include "list.h" #include "scheduler.h" #include "worker.h" //#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0) #define quit_if(cond) do {if (cond) {printf("Line %d.",__LINE__);exit(EXIT_FAILURE);}} while(0) void args_to_nums(int argc, const char **argv, int *num_workers, int *queue_size, int **quanta) { int i; quit_if(argc < 4); *num_workers = atoi(argv[1]); *queue_size = atoi(argv[2]); *quanta = malloc(*num_workers * sizeof(int)); quit_if(*quanta == NULL); for(i=3;i<argc;i++) quanta[0][i-3] = atoi(argv[i]); } void nums_to_args(int num_workers, int queue_size, int *quanta, int *argc, char ***argv) { int i; *argc = num_workers+3; *argv = malloc(*argc*sizeof(char *)); quit_if(*argv==NULL); argv[0][0] = "scheduler"; argv[0][1] = malloc(3*sizeof(char)); quit_if(argv[0][1]==NULL);
  • 21. sprintf(argv[0][1],"%d",num_workers); argv[0][2] = malloc(3*sizeof(char)); quit_if(argv[0][2]==NULL); sprintf(argv[0][2],"%d",queue_size); for(i=0;i<num_workers;i++) { argv[0][i+3] = malloc(3*sizeof(char)); quit_if(argv[0][i+3]==NULL); sprintf(argv[0][i+3],"%d",quanta[i]); } argv[0][i+3]=NULL; } /* Prepare input, reroute file descriptors, and run the program. */ void run_test(int argc, const char **argv) { //int fork_pid = fork(); //if (fork_pid == 0) { /* Reroute standard file descriptors */ freopen("smp5.out", "w", stdout); /* Run the program */ quit_if(smp5_main(argc, argv) != EXIT_SUCCESS); fclose(stdout); //} else if (fork_pid > 0) { //waitpid(fork_pid, 0, 0); //} else { //fprintf(stderr, "run_test: fork() errorn"); //} } int test_output(FILE *stream, int nw, int qs, int *q) { int queue_size, queue_index; int num_workers, worker_index; int rv, in_queue, term, susp; unsigned long *queue, *workers, tid, prev, newwork, dummyl;
  • 22. int *remaining, *quanta; char dummyc; float tot_wait, tot_run, ave_wait, ave_run; int my_run, my_wait; rv = fscanf(stream,"Main: running %d workers with queue size %d for quanta:n",&num_workers, &queue_size); quit_if(rv != 2 || num_workers != nw || queue_size != qs); queue = malloc(queue_size*sizeof(long)); workers = malloc(num_workers*sizeof(long)); quanta = malloc(num_workers*sizeof(int)); remaining = malloc(queue_size*sizeof(int)); for(worker_index=0;worker_index<num_workers;worker_index ++) { quit_if(fscanf(stream, " %d", quanta+worker_index) != 1); quit_if(quanta[worker_index]!=q[worker_index]); } fscanf(stream,"n"); for(worker_index=0;worker_index<num_workers;worker_index ++) { quit_if(fscanf(stream, "Main: detaching worker thread %lu.n",workers+worker_index) != 1); } quit_if(fscanf(stream, "Main: waiting for scheduler %lu.n",&dummyl) != 1); for(;queue_index<queue_size;queue[queue_index++]=0); worker_index = queue_index=0; in_queue = 0; quit_if(fscanf(stream, "Scheduler: waiting for workers.%c",&dummyc)!=1 || dummyc != 'n'); for(queue_index = 0;queue_index < queue_size &&
  • 23. queue_index < num_workers;queue_index++) { quit_if(fscanf(stream, "Thread %lu: in scheduler queue.n",&tid)!= 1 || tid != workers[worker_index]); quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)!= 1 || tid != workers[worker_index]); queue[queue_index]=tid; remaining[queue_index] = quanta[worker_index]; worker_index++; in_queue++; } my_run=0; my_wait = num_workers; queue_index = 0; term = susp = 0; while(worker_index < num_workers || in_queue > 0) { while(!queue[queue_index]) queue_index= (queue_index+1)%queue_size; quit_if(fscanf(stream, "Scheduler: scheduling.%c",&dummyc)!=1 || dummyc != 'n'); quit_if(fscanf(stream, "Scheduler: resuming %lu.n",&tid) != 1); quit_if( tid != queue[queue_index]); if (prev == tid) { if(term) { quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid) != 1 || tid != prev); } else if (susp){ quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid) != 1); quit_if( tid != prev); } quit_if(fscanf(stream, "Thread %lu: resuming.n",&tid) != 1); quit_if(tid != queue[queue_index]); } else { quit_if(fscanf(stream, "Thread %lu: resuming.n",&tid) != 1
  • 24. || tid != queue[queue_index]); if(term) { if(queue_size == 1) quit_if(fscanf(stream, "Scheduler: waiting for workers.%c",&dummyc)!=1 || dummyc!='n'); quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid) != 1 || tid != prev); if (in_queue == queue_size) { quit_if(fscanf(stream, "Thread %lu: in scheduler queue.n",&tid)!=1||tid != newwork); quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)!=1 || tid!=newwork); } } else if (susp && in_queue>1){ quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid) != 1); quit_if( tid != prev); prev = tid; } } quit_if(fscanf(stream, "Scheduler: suspending %lu.n",&tid) != 1); quit_if(tid != queue[queue_index]); if(!--remaining[queue_index]) { quit_if(fscanf(stream, "Thread %lu: leaving scheduler queue.n",&tid)!=1 || tid != queue[queue_index]); term = 1; if(worker_index < num_workers) { queue[queue_index] = workers[worker_index]; remaining[queue_index] = quanta[worker_index]; newwork = workers[worker_index]; worker_index++; if(queue_size == 1) { prev = tid; quit_if(fscanf(stream, "Scheduler: waiting for
  • 25. workers.%c",&dummyc)!=1 || dummyc!='n'); quit_if(fscanf(stream, "Thread %lu: terminating.n",&tid) != 1 || tid != prev); quit_if(fscanf(stream, "Thread %lu: in scheduler queue.n",&tid)!= 1 || tid != newwork); quit_if(fscanf(stream, "Thread %lu: suspending.n",&tid)!= 1 || tid != newwork); term = 0; susp = 0; my_wait++; } } else { queue[queue_index] = 0; in_queue--; } } else { term = 0; susp = 1; } prev = tid; my_run++; my_wait += in_queue+(num_workers-worker_index)-1+term; queue_index= (queue_index+1)%queue_size; } quit_if(fscanf(stream, "Th%c",&dummyc) != 1); if (dummyc=='r') { quit_if(fscanf(stream, "ead %lu: terminating.nThe",&tid)!=1 || tid != prev); } quit_if(fscanf(stream, " total wait time is %f seconds.n",&tot_wait) != 1); quit_if(fscanf(stream, "The total run time is %f seconds.n",&tot_run) != 1); quit_if(fscanf(stream, "The average wait time is %f seconds.n",&ave_wait) != 1); quit_if(fscanf(stream, "The average run time is %f
  • 26. seconds.n",&ave_run) != 1); if (dummyc=='e') quit_if(fscanf(stream, "Thread %lu: terminating.nThe",&tid) != 1|| tid != prev); quit_if(abs(tot_wait-my_wait)>1); quit_if(abs(tot_run-my_run)>1); quit_if(abs(tot_wait/num_workers-ave_wait)>.5); quit_if(abs(tot_run/num_workers-ave_run)>.5); return 0; } int general_test(int argc, const char **argv) { FILE *f; int nw, qs, *q; run_test(argc,argv); f = fopen("smp5.out","r"); args_to_nums(argc,argv,&nw,&qs,&q); test_output(f,nw,qs,q); return EXIT_SUCCESS; } int specific_test(int nw, int qs, int *q) { FILE *f; int argc; char **argv; nums_to_args(nw,qs,q,&argc,&argv); run_test(argc,(const char **)argv); f = fopen("smp5.out","r"); test_output(f,nw,qs,q); return EXIT_SUCCESS; } int test_3_1_2_2_2() { int q[3] = {2,2,2}; return specific_test(3,1,q);
  • 27. } int test_2_2_2_2() { int q[2]={2,2}; return specific_test(2,2,q); } int test_5_7_1_2_1_2_1() { int q[5] = {1,2,1,2,1}; return specific_test(5,7,q); } int test_4_1_1_2_3_4() { int q[4] = {1,2,3,4}; return specific_test(4,1,q); } int test_3_3_4_3_2() { int q[3] = {4,3,2}; return specific_test(3,3,q); } /* * Main entry point for SMP% test harness */ int run_smp5_tests(int argc, const char **argv) { /* Tests can be invoked by matching their name or their suite name * or 'all' */ testentry_t tests[] = { {"test_3_1_2_2_2", "rr", test_3_1_2_2_2}, {"test_2_2_2_2", "rr", test_2_2_2_2}, {"test_5_7_1_2_1_2_1", "rr", test_5_7_1_2_1_2_1}, {"test_4_1_1_2_3_4", "rr", test_4_1_1_2_3_4}, {"test_3_3_4_3_2", "rr", test_3_3_4_3_2},
  • 28. {"general", "gen", general_test} }; int result = run_testrunner(argc, argv, tests, sizeof(tests) / sizeof(testentry_t)); unlink("smp5.out"); return result; } /* The real main function. */ int main(int argc, const char **argv) { if (argc > 1 && !strcmp(argv[1], "-test")) { return run_smp5_tests(argc - 1, argv + 1); } else { return smp5_main(argc, argv); } } __MACOSX/assign3/assign3_part2/._smp5_tests.c assign3/assign3_part2/testrunner.h /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ typedef int (*test_fp) (int, const char **); typedef struct { const char *name; const char *suite; test_fp test_function; } testentry_t; int run_testrunner(int argc, const char **argv, testentry_t * entries, int entry_count);
  • 29. void set_testrunner_default_timeout(int s); void set_testrunner_timeout(int s); __MACOSX/assign3/assign3_part2/._testrunner.h assign3/assign3_part2/worker.h #ifndef __WORKER_H_ #define __WORKER_H_ void cancel_thread(); void suspend_thread(); void leave_scheduler_queue(thread_info_t*); #endif __MACOSX/assign3/assign3_part2/._worker.h assign3/assign3_part2/list.h #ifndef __LIST_H_ #define __LIST_H_ #include <pthread.h> typedef struct list_elem { struct list_elem *prev; struct list_elem *next; void *info; } list_elem; typedef struct thread_info_list { list_elem *head; list_elem *tail; pthread_mutex_t lock; } thread_info_list;
  • 30. int list_size(thread_info_list *list); int list_insert_head(thread_info_list *list, list_elem *new); int list_insert_tail(thread_info_list *list, list_elem *new); int list_remove(thread_info_list *list, list_elem *new); void print_list(thread_info_list *list); #endif /* __LIST_H_ */ __MACOSX/assign3/assign3_part2/._list.h assign3/assign3_part2/README.txt SMP5: Scheduler with Signals ============================ This MP is a variation of SMP4. In the last MP, we built a simulated OS process scheduler. The scheduler can hold only a certain number of processes (workers) at one time. Once the process has been accepted into the scheduler, the scheduler decides in what order the processes execute. We implemented two scheduling algorithms: FIFO and Round Robin. In this MP, we are to simulate a time-sharing system by using signals and timers. We will only implement the Round Robin algorithm. Instead of using iterations to model the concept of "time slices" (as in the last MP), we use interval timers. The scheduler is installed with an interval timer. The timer starts ticking when the scheduler picks a thread to use the CPU
  • 31. which in turn signals the thread when its time slice is finished thus allowing the scheduler to pick another thread and so on. When a thread has completely finished its work it leaves the scheduler to allow a waiting thread to enter. Please note that in this MP, only the timer and scheduler send signals. The threads passively handle the signals without signaling back to the scheduler. The program takes a number of arguments. Arg1 determines the number of jobs (threads in our implementation) created; arg2 specifies the queue size of the scheduler. Arg3 through argN gives the duration (the required time slices to complete a job) of each job. Hence if we create 2 jobs, we should supply arg3 and arg4 for the required duration. You can assume that the autograder will always supply the correct number of arguments and hence you do not have to detect invalid input. Here is an example of program output, once the program is complete: % scheduler 3 2 3 2 3 Main: running 3 workers with queue size 2 for quanta: 3 2 3 Main: detaching worker thread 3075926960. Main: detaching worker thread 3065437104. Main: detaching worker thread 3054947248. Main: waiting for scheduler 3086416816. Scheduler: waiting for workers.
  • 32. Thread 3075926960: in scheduler queue. Thread 3075926960: suspending. Thread 3065437104: in scheduler queue. Thread 3065437104: suspending. Scheduler: scheduling. Scheduler: resuming 3075926960. Thread 3075926960: resuming. Scheduler: suspending 3075926960. Scheduler: scheduling. Scheduler: resuming 3065437104. Thread 3065437104: resuming. Thread 3075926960: suspending. Scheduler: suspending 3065437104. Scheduler: scheduling. Scheduler: resuming 3075926960. Thread 3075926960: resuming. Thread 3065437104: suspending. Scheduler: suspending 3075926960. Scheduler: scheduling. Scheduler: resuming 3065437104. Thread 3065437104: resuming. Thread 3075926960: suspending. Scheduler: suspending 3065437104. Thread 3065437104: leaving scheduler queue. Scheduler: scheduling. Scheduler: resuming 3075926960. Thread 3075926960: resuming. Thread 3065437104: terminating. Thread 3054947248: in scheduler queue. Thread 3054947248: suspending. Scheduler: suspending 3075926960. Thread 3075926960: leaving scheduler queue. Scheduler: scheduling. Scheduler: resuming 3054947248. Thread 3054947248: resuming. Thread 3075926960: terminating.
  • 33. Scheduler: suspending 3054947248. Scheduler: scheduling. Scheduler: resuming 3054947248. Thread 3054947248: suspending. Thread 3054947248: resuming. Scheduler: suspending 3054947248. Scheduler: scheduling. Scheduler: resuming 3054947248. Thread 3054947248: suspending. Thread 3054947248: resuming. Scheduler: suspending 3054947248. Thread 3054947248: leaving scheduler queue. Thread 3054947248: terminating. The total wait time is 12.062254 seconds. The total run time is 7.958618 seconds. The average wait time is 4.020751 seconds. The average run time is 2.652873 seconds. The goal of this MP is to help you understand (1) how signals and timers work, and (2) how to evaluate the performance of your program. You will first implement the time-sharing system using timers and signals. Then, you will evaluate the overall performance of your program by keeping track of how long each thread is idle, running, etc. The program will use these four signals: SIGALRM: sent by the timer to the scheduler, to indicate another time quantum has passed. SIGUSR1: sent by the scheduler to a worker, to tell it to suspend.
  • 34. SIGUSR2: sent by the scheduler to a suspended worker, to tell it to resume. SIGTERM: sent by the scheduler to a worker, to tell it to cancel. You will need to set up the appropriate handlers and masks for these signals. You will use these functions: clock_gettime pthread_sigmask pthread_kill sigaction sigaddset sigemptyset sigwait timer_settime timer_create Also, make sure you understand how the POSIX:TMR interval timer works. There are two ways you can test your code. You can run the built-in grading tests by running "scheduler -test -f0 rr". This runs 5 tests, each of which can be run individually. You can also test you program with specific parameters by running "scheduler -test gen ..." where the ellipsis contains the parameters you would pass to scheduler. Programming ===========
  • 35. Part I: Modify the scheduler code (scheduler.c) ----------------------------------------------- We use the scheduler thread to setup the timer and handle the scheduling for the system. The scheduler handles the SIGALRM events that come from the timer, and sends out signals to the worker threads. Step 1. Modify the code in init_sched_queue() function in scheduler.c to initialize the scheduler with a POSIX:TMR interval timer. Use CLOCK_REALTIME in timer_create(). The timer will be stored in the global variable "timer", which will be started in scheduler_run() (see Step 4 below). Step 2. Implement setup_sig_handlers(). Use sigaction() to install signal handlers for SIGALRM, SIGUSR1, and SIGTERM. SIGALRM should trigger timer_handler(), SIGUSR1 should trigger suspend_thread(), and SIGTERM should trigger cancel_thread(). Notice no handler is installed for SIGUSR2; this signal will be handled differently, in step 8. Step 3. In the scheduler_run() function, start the timer. Use
  • 36. timer_settime(). The time quantum (1 second) is given in scheduler.h. The timer should go off repeatedly at regular intervals defined by the timer quantum. In Round-Robin, whenever the timer goes off, the scheduler suspends the currently running thread, and tells the next thread to resume its operations using signals. These steps are listed in timer_handler(), which is called every time the timer goes off. In this implementation, the timer handler makes use of suspend_worker() and resume_worker() to accomplush these steps. Step 4. Complete the suspend_worker() function. First, update the info->quanta value. This is the number of quanta that remain for this thread to execute. It is initialized to the value passed on the command line, and decreases as the thread executes. If there is any more work for this worker to do, send it a signal to suspend, and update the scheduler queue. Otherwise, cancel the thread. Step 5. Complete the cancel_worker() function by sending the appropriate signal to the thread, telling it to kill itself. Step 6.
  • 37. Complete the resume_worker() function by sending the appropriate signal to the thread, telling it to resume execution. Part II: Modify the worker code (worker.c) ------------------------------------------ In this section, you will modify the worker code to correctly handle the signals from the scheduler that you implemented in the previous section. You need to modify the thread functions so that it immediately suspends the thread, waiting for a resume signal from the scheduler. You will need to use sigwait() to force the thread to suspend itself and wait for a resume signal. You need also to implement a signal handler in worker.c to catch and handle the suspend signals. Step 7. Modify start_worker() to (1) block SIGUSR2 and SIGALRM, and (2) unblock SIGUSR1 and SIGTERM. Step 8. Implement suspend_thread(), the handler for the SIGUSR1 signal. The thread should block until it receives a resume (SIGUSR2) signal.
  • 38. Part III: Modify the evaluation code (scheduler.c) -------------------------------------------------- This program keeps track of run time, and wait time. Each thread saves these two values regarding its own execution in its thread_info_t. Tracking these values requires also knowing the last time the thread suspended or resumed. Therefore, these two values are also kept in thread_info_t. See scheduler.h. In this section, you will implement the functions that calculate run time and wait time. All code that does this will be in scheduler.c. When the program is done, it will collect all these values, and print out the total and average wait time and run time. For your convenience, you are given a function time_difference() to compute the difference between two times in microseconds. Step 9. Modify create_workers() to initialize the various time variables. Step 10. Implement update_run_time(). This is called by suspend_worker(). Step 11.
  • 39. Implement update_wait_time(). This is called by resume_worker(). Questions ========== Question 1. Why do we block SIGUSR2 and SIGALRM in worker.c? Why do we unblock SIGUSR1 and SIGTERM in worker.c? Question 2. We use sigwait() and sigaction() in our code. Explain the difference between the two. (Please explain from the aspect of thread behavior rather than syntax). Question 3. When we use POSIX:TMR interval timer, we are using relative time. What is the alternative? Explain the difference between the two. Question 4. Look at start_worker() in worker.c, a worker thread is executing within an infinite loop at the end. When does a worker thread terminate? Question 5. When does the scheduler finish? Why does it not exit when the scheduler queue is empty? Question 6. After a thread is scheduled to run, is it still in the sched_queue? When is it
  • 40. removed from the head of the queue? When is it removed from the queue completely? Question 7. We've removed all other condition variables in SMP4, and replaced them with a timer and signals. Why do we still use the semaphore queue_sem? Question 8. What's the purpose of the global variable "completed" in scheduler.c? Why do we compare "completed" with thread_count before we wait_for_queue() in next_worker()? Question 9. We only implemented Round Robin in this SMP. If we want to implement a FIFO scheduling algorithm and keep the modification as minimum, which function in scheduler.c is the one that you should modify? Briefly describe how you would modify this function. Question 10. In this implementation, the scheduler only changes threads when the time quantum expires. Briefly explain how you would use an additional signal to allow the scheduler to change threads in the middle of a time quantum. In what situations would this be useful? __MACOSX/assign3/assign3_part2/._README.txt
  • 41. assign3/assign3_part2/scheduler.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <time.h> #include <signal.h> #include "scheduler.h" #include "worker.h" /* * define the extern global variables here. */ sem_t queue_sem; /* semaphore for scheduler queue */ thread_info_list sched_queue; /* list of current workers */ static int quit = 0; static timer_t timer; static thread_info_t *currentThread= 0; static long wait_times; static long run_times; static int completed = 0; static int thread_count = 0; static void exit_error(int); /* helper function. */ static void wait_for_queue(); /**************************************************** *************************** * * Implement these functions. *
  • 42. ***************************************************** *************************/ /* * This function intializes the queue semaphore and the queue itself. */ /* * Update the worker's current running time. * This function is called every time the thread is suspended. */ void update_run_time(thread_info_t *info) { /* TODO: implement this function */ } /* * Update the worker's current waiting time. * This function is called every time the thread resumes. */ void update_wait_time(thread_info_t *info) { /* TODO: implement this function */ } static void init_sched_queue(int queue_size) { /* set up a semaphore to restrict access to the queue */ sem_init(&queue_sem, 0, queue_size); /* initialize the scheduler queue */ sched_queue.head = sched_queue.tail = 0; pthread_mutex_init(&sched_queue.lock, NULL); /* TODO: initialize the timer */
  • 43. } /* * signal a worker thread that it can resume. */ static void resume_worker(thread_info_t *info) { printf("Scheduler: resuming %lu.n", info->thrid); /* * TODO: signal the worker thread that it can resume */ /* update the wait time for the thread */ update_wait_time(info); } /*send a signal to the thread, telling it to kill itself*/ void cancel_worker(thread_info_t *info) { /* TODO: send a signal to the thread, telling it to kill itself*/ /* Update global wait and run time info */ wait_times += info->wait_time; run_times += info->run_time; completed++; /* Update schedule queue */ leave_scheduler_queue(info); if (completed >= thread_count) { sched_yield(); /* Let other threads terminate. */ printf("The total wait time is %f seconds.n",
  • 44. (float)wait_times / 1000000); printf("The total run time is %f seconds.n", (float)run_times / 1000000); printf("The average wait time is %f seconds.n", (float)wait_times / 1000000 / thread_count); printf("The average run time is %f seconds.n", (float)run_times / 1000000 / thread_count); } } /* * signals a worker thread that it should suspend. */ static void suspend_worker(thread_info_t *info) { int whatgoeshere = 0; printf("Scheduler: suspending %lu.n", info->thrid); /*update the run time for the thread*/ update_run_time(info); /* TODO: Update quanta remaining. */ /* TODO: decide whether to cancel or suspend thread */ if(whatgoeshere) { /* * Thread still running: suspend. * TODO: Signal the worker thread that it should suspend. */ /* Update Schedule queue */ list_remove(&sched_queue,info->le); list_insert_tail(&sched_queue,info->le); } else {
  • 45. /* Thread done: cancel */ cancel_worker(info); } } /* * this is the scheduling algorithm * pick the next worker thread from the available list * you may need to add new information to the thread_info struct */ static thread_info_t *next_worker() { if (completed >= thread_count) return 0; wait_for_queue(); printf("Scheduler: scheduling.n"); /* return the thread_info_t for the next thread to run */ return sched_queue.head->info; } void timer_handler() { thread_info_t *info = 0; /* once the last worker has been removed, we're done. */ if (list_size(&sched_queue) == 0) { quit = 1; return; } /*suspend the current worker*/ if (currentThread) suspend_worker(currentThread);
  • 46. //resume the next worker info = next_worker(); /* Update currentThread */ currentThread = info; if (info) resume_worker(info); else quit = 1; } /* * Set up the signal handlers for SIGALRM, SIGUSR1, and SIGTERM. * TODO: Implement this function. */ void setup_sig_handlers() { /* Setup timer handler for SIGALRM signal in scheduler */ /* Setup cancel handler for SIGTERM signal in workers */ /* Setup suspend handler for SIGUSR1 signal in workers */ } /**************************************************** *************************** * * * *****************************************************
  • 47. *************************/ /* * waits until there are workers in the scheduling queue. */ static void wait_for_queue() { while(!list_size(&sched_queue)) { printf("Scheduler: waiting for workers.n"); sched_yield(); } } /* * runs at the end of the program just before exit. */ static void clean_up() { /* * destroy any mutexes/condition variables/semaphores that were created. * free any malloc'd memory not already free'd */ sem_destroy(&queue_sem); pthread_mutex_destroy(&sched_queue.lock); } /* * prints the program help message. */ static void print_help(const char *progname) { printf("usage: %s <num_threads> <queue_size> <i_1, i_2 ... i_numofthreads>n", progname); printf("tnum_threads: the number of worker threads to
  • 48. runn"); printf("tqueue_size: the number of threads that can be in the scheduler at one timen"); printf("ti_1, i_2 ...i_numofthreads: the number of quanta each worker thread runsn"); } /* * prints an error summary and exits. */ static void exit_error(int err_num) { fprintf(stderr, "failure: %sn", strerror(err_num)); exit(1); } /* * creates the worker threads. */ static void create_workers(int thread_count, int *quanta) { int i = 0; int err = 0; for (i = 0; i < thread_count; i++) { thread_info_t *info = (thread_info_t *) malloc(sizeof(thread_info_t)); info->quanta = quanta[i]; if ((err = pthread_create(&info->thrid, NULL, start_worker, (void *)info)) != 0) { exit_error(err); } printf("Main: detaching worker thread %lu.n", info- >thrid); pthread_detach(info->thrid);
  • 49. /* TODO: initialize the time variables for each thread for performance evalution*/ } } /* * runs the scheduler. */ static void *scheduler_run(void *unused) { wait_for_queue(); /* TODO: start the timer */ /*keep the scheduler thread alive*/ while( !quit ) sched_yield(); return NULL; } /* * starts the scheduler. * returns 0 on success or exits program on failure. */ static int start_scheduler(pthread_t *thrid) { int err = 0; if ((err = pthread_create(thrid, NULL, scheduler_run, 0)) != 0) { exit_error(err); }
  • 50. return err; } /* * reads the command line arguments and starts the scheduler & worker threads. */ int smp5_main(int argc, const char** argv) { int queue_size = 0; int ret_val = 0; int *quanta,i; pthread_t sched_thread; /* check the arguments. */ if (argc < 3) { print_help(argv[0]); exit(0); } thread_count = atoi(argv[1]); queue_size = atoi(argv[2]); quanta = (int*)malloc(sizeof(int)*thread_count); if (argc != 3 + thread_count) { print_help(argv[0]); exit(0); } for ( i = 0; i < thread_count; i++) quanta[i] = atoi(argv[i+3]); printf("Main: running %d workers with queue size %d for quanta:n", thread_count, queue_size); for ( i = 0; i < thread_count; i++) printf(" %d", quanta[i]); printf("n");
  • 51. /*setup the sig handlers for scheduler and workers*/ setup_sig_handlers(); /* initialize anything that needs to be done for the scheduler queue. */ init_sched_queue(queue_size); /* creates a thread for the scheduler. */ start_scheduler(&sched_thread); /* creates the worker threads and returns. */ create_workers(thread_count, quanta); /* wait for scheduler to finish */ printf("Main: waiting for scheduler %lu.n", sched_thread); pthread_join(sched_thread, (void **) &ret_val); /* clean up our resources */ clean_up(); /* this will wait for all other threads */ pthread_exit(0); } long time_difference(const struct timespec *time1, const struct timespec *time2) { return (time1->tv_sec - time2->tv_sec) * 1000000 + (time1->tv_nsec - time2->tv_nsec) / 1000; } __MACOSX/assign3/assign3_part2/._scheduler.c assign3/assign3_part2/testrunner.c
  • 52. /*************** YOU SHOULD NOT MODIFY ANYTHING IN THIS FILE ***************/ /* A simple testrunner framework Original Author: L. Angrave */ #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <unistd.h> #include "testrunner.h" /* Constants */ #define false (0) #define true (1) #define test_killed (2) /* defaults */ static int default_timeout_seconds = 15; static int timeout_seconds; void set_testrunner_default_timeout(int s) { assert(s > 0); default_timeout_seconds = s; } void set_testrunner_timeout(int s) { assert(s > 0);
  • 53. timeout_seconds = s; } /* --- Helper macros and functions --- */ #define DIE(mesg) {fprintf(stderr,"n%s(%d):%sn",__fname__,__LINE__,mesg); exit(1);} static int eql(const char *s1, const char *s2) { return s1 && s2 && !strcmp(s1, s2); } /* Callback function for qsort on strings */ static int mystrcmp(const void *p1, const void *p2) { return eql((const char *) p1, (const char *) p2); } /* Stats of all tests run so far */ typedef struct { int ran, passed, failed; } stats_t; /* -- Signal handlers -- */ static pid_t child_pid; static int sent_child_timeout_kill_signal; static void kill_child_signal_handler(intsigno) { if (!child_pid) return; char m[] = "-Timeout(Killing test process)-"; write(0, m, sizeof(m) - 1); kill(child_pid, SIGKILL); sent_child_timeout_kill_signal = 1; }
  • 54. /* Internal function to run a test as a forked child. The child process is terminated if it runs for more than a few seconds */ static int invoke_test_with_timelimit(testentry_t * test, int redirect_stdouterr, int argc, const char **argv) { char fname[255]; int wait_status; pid_t wait_val; struct sigaction action; assert(!child_pid); assert(test && test->test_function && test->name); set_testrunner_timeout(default_timeout_seconds); errno = 0; child_pid = fork(); if (child_pid == -1) { fprintf(stderr, "-fork failed so running test inline-"); return test->test_function(argc, argv); } if (child_pid == 0) { if (redirect_stdouterr) { snprintf(fname, (int) sizeof(fname), "stdout-%s.txt", test->name); fname[sizeof(fname) - 1] = 0; freopen(fname, "w", stdout); memcpy(fname + 3, "err", 3); freopen(fname, "w", stderr);
  • 55. } exit(test->test_function(argc, argv)); } else { wait_status = -1; sigemptyset(&action.sa_mask); action.sa_handler = kill_child_signal_handler; sigaction(SIGALRM, &action, NULL); sent_child_timeout_kill_signal = 0; alarm(timeout_seconds); wait_val = waitpid(child_pid, &wait_status, 0); int child_exited_normally = WIFEXITED(wait_status); int child_exit_value = WEXITSTATUS(wait_status); int child_term_by_signal = WIFSIGNALED(wait_status); int child_term_signal = WTERMSIG(wait_status); if (child_term_by_signal) { fprintf(stderr, "testrunner:Test terminated by signal %dn", child_term_signal); fprintf(stderr, "testrunner:waitpid returned %d (child_pid=%d,wait_status=%d)", wait_val, child_pid, wait_status); } if (child_pid != wait_val) fprintf(stderr, "testrunner: strange... wait_val != child_pidn"); int passed = (child_pid == wait_val) && (child_exit_value == 0) && (child_exited_normally != 0);
  • 56. alarm(0); kill(child_pid, SIGKILL); child_pid = 0; return sent_child_timeout_kill_signal ? test_killed : passed ? 0 : 1; } } /* * run a test and update the stats. The main guts of this functionality is provided by invoke_test_with_timelimit * This outer wrapper updates thes output and statistics before and after running the test. */ static int run_one_test(stats_t * stats, testentry_t * test, int redirect_stdouterr, int argc, const char **argv) { int test_result; assert(stats && test->name && argc > 0 && argv && *argv); stats->ran++; stats->failed++; printf("%2d.%-20s:", stats->ran, test->name); fflush(stdout); test_result = invoke_test_with_timelimit(test, redirect_stdouterr, argc, argv);
  • 57. if (test_result == 0) { stats->failed--; stats->passed++; } printf(":%sn", (test_result == 0 ? "pass" : test_result == 2 ? "TIMEOUT * " : "FAIL *")); return test_result != 0; } /* Help functionality to print out sorted list of test names and suite names */ static void print_targets(testentry_t tests[], int count) { const char **array; const char *previous; int i; array = (const char **) calloc(sizeof(const char *), count); /* Sort the test names and print unique entries */ for (i = 0; i < count; i++) array[i] = tests[i].name; qsort(array, count, sizeof(array[0]), mystrcmp); printf("nValid tests : all"); for (i = 0, previous = ""; i < count; i++) if (!eql(previous, array[i])) printf(" %s", (previous = array[i])); /* Sort the suite names and print unique entries */ for (i = 0; i < count; i++) array[i] = tests[i].suite; qsort(array, count, sizeof(array[0]), mystrcmp);
  • 58. printf("nValid suites:"); for (i = 0, previous = ""; i < count; i++) if (!eql(previous, array[i])) printf(" %s", (previous = array[i])); printf("n"); } /* * Main entry point for test harness */ int run_testrunner(int argc, const char **argv, testentry_t tests[], int test_count) { const char *test_name, *target; int i; stats_t stats; int target_matched, max_errors_before_quit, redirect_stdouterr; memset(&stats, 0, sizeof(stats)); max_errors_before_quit = 1; redirect_stdouterr = 0; assert(tests != NULL); assert(test_count > 0); assert(argc > 0 && argv && *argv); while (true) { target = argc > 1 ? argv[1] : ""; assert(target); if (*target != '-') break; argc--;
  • 59. argv++; if (target[1] == 'f' && target[2]) max_errors_before_quit = atoi(target + 1); else if (target[1] == 'r') redirect_stdouterr = 1; } target_matched = false; for (i = 0; i < test_count && (max_errors_before_quit < 1 || stats.failed != max_errors_before_quit); i++) { test_name = tests[i].name; assert(test_name); assert(tests[i].suite); assert(tests[i].test_function); if (eql(target, test_name) || eql(target, "all") || eql(target, tests[i].suite)) { if (!target_matched) printf("Running tests...n"); target_matched = true; run_one_test(&stats, &tests[i], redirect_stdouterr, argc - 1, argv + 1); } } if (!target_matched) { fprintf(stderr, "Test '%s' not found", (strlen(target) > 0 ? target : "(empty)")); print_targets(tests, test_count); } else { printf("nTest Results:%d tests,%d passed,%d failed.n", stats.ran, stats.passed, stats.failed);
  • 60. } return stats.passed == stats.ran && target_matched ? 0 : 1; } __MACOSX/assign3/assign3_part2/._testrunner.c “Social Change” Program Transcript HOLLY HOEY: So Maurice, as we talk about social change, I
  • 61. know there's a story behind how you got into this field. I can just sense your passion and enthusiasm for what you do. MAURICE WILLIAMS: Well, I've always had an interest in the human condition. My undergrad was in psychology, so we studied a lot about the mind, human behavior. I've always been inquisitive. I want to know; how did we get here, who are we, why are we so different, why are we so alike, what makes us who we are? And so, literally, that's why I got into it. Now, as I started working in the field though, I saw that, wow, it's not about being inquisitive. There's really a lot of needs out here for people. There's a lot of pain out here. It's a lot of trauma, a lot of grief, a lot of loss. And I come from a family that has always been very community focused. And so I got into working with people with disabilities. And then next, I worked with adults who were on assistance, tenants assistance. And then I ended up working with children. And now it's like, "Wow, there it is." Children have such a vulnerability, but such a purity. I can connect with them, because children always remind me that we all were one of them at one time. And I'm fortunate enough to have gotten into a field that keeps me focused on, like Holly asked, What am I going to do good today? Who am I going to help? Not really
  • 62. save, but who am I going to help progress further in their life." HOLLY HOEY: What about you Andrea? ANDREA INGRAM: Well, I grew up in a large family, a lot of kids, and I was in the middle. So middle children, we do a lot of mediating and all this kind of stuff. But, I also grew up with a very keen sense of justice and fairness. When there are seven kids in the family, you learn that life is not fair. And my parents had a strong sense of justice also, and were great examples. So when I went out into the world, I felt an obligation, a responsibility to try to make life better for people that didn't have it as well as I did. Because to me, it's a sense of justice and fairness to include people in the mainstream who are left out, for whatever reason. They're left out because of poverty, they're left out because of mental illness, or there are left out because of their personality. They're just left out because of relationships. So it's just because of, I think, being raised with a keen sense of fairness and justice and wanting to have an impact on that.
  • 63. I found that I really loved crisis work, because when people are in crisis there's such energy there and motivation to make things different. And there's a real opportunity to make things different and to make some really significant changes and reach some really significant resolutions in your life that really might put you on a different path. HOLLY HOEY: I say that I'm in this field by default. But it worked out to my benefit, because I absolutely love what I do. I wasn't a middle child, but I've always been a mediator. Always. "Are you OK? Is everyone OK? Let's make sure
  • 64. everybody gets along." And so that's just my personality. But I have a degree in interior design. And so I did design work for five years. And I race walked a marathon for Leukemia Society, and we had to raise money. Here we go. Here goes my life story. And I had to raise money, which I found to be so simple. And people kept saying, "How are you raising all that money?" And I said, "It's because I believe in it." If I could talk about it and I believed in it, and I really had a case for why I was raising money, I found it to be very easy. And so here goes my career change. I loved it. And I said, "I'm not fulfilled in my previous job." And I just said, "I'm going to make a life change." And it was the best change that I made. And 12 years later, here I am. I love it at United Way. And I just feel that I connect the dots. That's my job. I connect the dots. I connect the dots with my volunteers, with donors, to people that need help. And United Way does the same thing with partners. And I just feel that that's where my skill set is. If I can bring these people together to effect change, I've done my job. So we're talking about how our organizations influence social change. And I think this is actually the most exciting part to discuss, because
  • 65. being at United Way for over 12 years, I think that my job every day is extremely rewarding and fulfilling. What United Way of Central Maryland does is to again, mobilize the community to improve people's lives. We are touching the lives and changing lives as it relates to helping people sustain their lives, to stabilize, and then getting them out of that spiraling poverty and getting them to self- sufficiency. My job is to educate and communicate and inform individuals about the most pressing needs in this community. MAURICE WILLIAMS: I, like you, Holly, believe that social change is very, very important for our organization as well, the Williams Life Center. We service people who are born into the number one institution, the first institution that they'll ever be a part of, which is the family. Unfortunately, their families fall apart for whatever reasons, neglect, abuse, drugs, incarceration. Some families and some parents want to take care of the kids, but they just don't have the resources and the capabilities to do so. And so we at the Williams Life Center bring them in.
  • 66. Some children come into our program and they've already lost a lot. And maybe they're now 14 already when they come into the system, and some of them have a long way to go. And they may falter and they may not be successful in the program that we provide to them. But then there are others, which far outweigh the ones that don't make it, that will come in and although they have the emotional baggage that they have, and the traumas that they've experienced, we
  • 67. watch them grow and we watch them become connected to a family. And that is so rewarding, because we see that as our duty to ensure that these children, no matter what their previous life would have been like, that when they come to our agency we're going to take care of them, bottom line. We're going to take care of them. And if they're in an environment that is not meeting the standard, we move them. And then those that aren't meeting the standard, but we can work with them to get them higher, we do that. And so that's how we believe we affect social change. Because this is another child who may not grow up to be an abuser himself. ANDREA INGRAM: Well, to me, social change is very personal. You talked about volunteers. You talked about your families and the kids. I think large change starts with one person, and it goes from that person to their family, to their congregation. An example that I would like to talk a little bit about is, we do a lot of services for people with mental illness. And they're in our shelter programs, but we also have a mobile crisis team and we go out with the police. We also do some training with the Police Department on how to better manage situations with a person who's perhaps having a psychotic episode, may be behaviorally out of
  • 68. control, resulting in some family conflict, and so forth. There's one person that we respond to all the time. When she's not in treatment, it can be pretty outrageous, including challenging the police, very confrontational. It could even be sexually oriented. When the police went to lunch at this day program, there she was. And it was at a point in her life where she was in treatment. And the police were just amazed. They sat down with her, were able to talk with her, see her when she is in treatment and is doing well. And were even able to talk to her about, how should we behave when we come out and you're in crisis? So that she could even have some input into how the police and the mobile crisis team would respond to her. That one thing transfers to other police officers, transfers to how they act when they respond to other people who are having a mental health crisis. Because they can see the person behind the crisis. And when you see the person behind the crisis, you handle it a little differently. So that to me is social change, one person at a time. MAURICE WILLIAMS: When we think of social change, sometimes I think we think of somebody standing behind a podium saying, "Let's do it," and there's hundreds of thousands of people out there on the lawn listening.
  • 69. But it's really one person at a time. And sometimes, in our jobs, we have to remind ourselves how important what we do really is. I was in Walmart two weeks ago, and a foster family came up to me and said, "Hey, Mr. Williams." And I turned around and it was a 16-year old who I had placed there over a year ago with her foster mother. And the 16- year old has a son who was born about a year or so ago. The son was born with extreme health needs. And so working with this child, she broke down. She said, "I'm in twelfth grade. My child is sick." The child was in the hospital for like three months at a time. And we said to her, "We will help you through this. We're going to ensure that you graduate. We're going to ensure that
  • 70. this baby is taken care of." And we stuck with her. And so when I walked away after we spoke, I looked back at them again and I said to myself, "Wow, that could have never happened had we not really worked to keep this girl together, to keep this baby together, to keep this family together." So sometimes, little glimpses will come that says, "You know what Maurice, what you guys do is really important." And so it is one individual at a time. It really is. © 2013 Laureate Education, Inc. 4