Supplementary for Project 1
Download
Report
Transcript Supplementary for Project 1
Project 1
Project 1
Supplemental Lecture
Joe Mongeluzzi
Jason Zhao
Cornell CS 4411, September 14, 2012
Project 1
Today’s Lecture
Administrative Information
C Pointer Hints
Project 1 FAQ
Q&A/Discussion
Project 1
Administrative Information
Project 1 due Sept. 21, 11:59 PM
Submission via CMS
Submit single zip file
don’t create an extra folder to hold the content
submit only source files, in addition to README
don’t encrypt!
Instructions will be posted on website
Correctness and elegance are prized
Comment code, use proper indentation, remove
excess debug (printf) statements
Project 1
Pointer casting
A pointer has two components:
starting address of the data being pointed to
size of data type associated with this memory location
int a = 66051;
int *x = &a;
x = 0x00001004
*x = 0x00010203
pointer x: data starts from 0x00001004 and spans 4 bytes
0x00001000
0
0
0
0
3
2
1
0x00001004
endianness?
0
0
0
0
0
0
0
0
0
Project 1
Pointer casting
Casting the pointer changes only the way the
memory is interpreted.
It does not change the memory contents or the
address stored in the pointer.
int
int
a = 66051;
*x = &a;
x
*x
y
*y
char *y;
y = (char*) x;
0
0
0x00001004
0x00010203
0x00001004
0x03
pointer y: data starts from 0x00001004 and spans 1 byte
pointer x: data starts from 0x00001004 and spans 4 bytes
0x00001000
0
=
=
=
=
0
3
0
2
0
0
1
0x00001004
0
0
0
0
0
0
0
0
0
Project 1
Pointer casting
We can change the values from the casted
pointer if we like.
No array bounds check in C!
int
a = 66501;
int *x = &a;
char *y = (char*) x;
x
*x
y
*y
y[2]
=
=
=
=
=
0
0
0x00001004
0x00010203
0x00001004
0x04
0x01
0x00001000
0
0
0
0
3
0
0
2
0
1
0x00001004
0
0
0
0
0
0
0
Project 1
Structures
struct base {
int first;
int second;
};
struct derived {
struct base original;
int third;
};
struct base* b;
struct derived* d;
pointer b: data starts from 0x00001000 and spans 8 bytes (struct is aligned)
0x00001000
0
0
first
0
0
0
0
0
second
0
0
0
0
0
0
0
0
0
Project 1
Structures
struct base {
int first;
int second;
};
struct derived {
struct base original;
int third;
};
struct base* b;
struct derived* d;
pointer d: data starts from 0x00001000 and spans 12 bytes (struct is aligned)
0x00001000
0
0
0
0
0
original
0
0
0
0
0
0
third
0
0
0
0
0
Project 1
Common questions on casting
Casting from a derived struct pointer to the base
struct pointer is safe
any operation that works on data members of the
base struct will not write outside of the space
allocated for the derived struct
struct base *b = (struct base*) d;
b->first = 0xdaed; b->second = 0xfeeb;
pointer d: data starts from 0x00001000 and spans 12 bytes (struct is aligned)
dc
ea
af
d
e
b
ea
b
e
ef
0
0
0
0
pointer b: data starts from 0x00001000 and spans 8 bytes.
Project 1
Common questions on casting
What about casting from base struct to derived
struct?
unless you are very sure you will not touch data fields
other than those in the base struct
but if that is the case, why did you perform the cast?
struct derived *some_d = (struct derived*) some_b;
some_d->first = 1;
some_d->second = 2;
some_d->third = 3;
Project 1
Common questions on casting
Writing outside of known bounds may cause
unpredictable behavior
may overwrite another variable
may overwrite stack (and thus modify return address;
a common exploit)
usually just crashes
struct derived *some_d = (struct derived*) some_b;
some_d->first = 1;
some_d->second = 2;
some_d->third = 3;
Project 1
void* pointers
Review: a pointer has two components
starting address of the data being pointed to
size of data type associated with this memory location
void* pointers are not associated with any data
type
has only a starting address
no known size, therefore not possible to tell where
data ends in memory
malloc() is a good example
Project 1
Casting void* pointers
casting to void* from other pointer types
automatic, no need to prepend (void*)
other pointers can easily cast to void*; just ignore the
size of the data type
casting to other pointer types from void*
explicit cast required
destination data type supplies the size of the data
type
Project 1
Queue
All* queue operations take in an existing queue.
int queue_append(queue_t, void *item);
Append takes a pointer to an existing object, it is your job
to link that pointer/object to the rest of your queue
int queue_deque(queue_t queue, void **item);
Dequeue removes the first item from the queue and
returns it to the caller via the variable “item”
int queue_delete(queue_t queue, void **item);
Delete takes a pointer to the exact element that you
appended and removes it from the queue
*all queue functions except queue_new()
Project 1
Queue Abstraction
Head
Ptr1
Ptr2
Ptr3
Ptr4
Obj1
Obj2
Obj3
Obj4
myPtr
Queue_dequeue(myQ, myPtr)
dPtr
Queue_delete(myQ, dPtr)
Project 1
Queue
int queue_iterate(queue_t, PFAny, void *);
Iterate applies a functions f to all elements of the
queue. Corner cases, if any application of the function
f fails (i.e., returns a -1), immediately terminate the
iteration and return -1.
int queue_free(queue_t);
Free returns all memory allocated to the queue
structure back to the OS. Free does not free the
memory of the actual objects stored in the queue.
Project 1
Queue
General *Pointers:
Return correct error codes in all cases – unlike Java,
C does not have exceptions therefore you must
ensure your queue returns the correct error code
when something goes wrong.
Check your code for memory leaks – Visual Studio
provides tools for detecting memory leaks but you
should still reason about your code!
Project 1
Minithread
Minithreads are the fundamental building block of
your OS
You must implement the entire infrastructure to
support minithreads including but not limited to:
Thread creation
Thread state (TCB)
Context switching
Thread blocking
Thread cleanup/deletion
As an OS, you must NEVER terminate. This is
achieved using an idle thread.
What should the idle thread do?
Project 1
Typical PortOS Execution
Thread
Creation
System Initialize
Thread
Execution
Ready
Idle Thread
Waiting
Thread
Deletion
Thread
Termination
Running
Project 1
Semaphore
Low level synchronization primitive
What is the purpose of a semaphore?
Mutual exclusion
Eliminates busy waiting
Common operations
semaphore_P – “procures” the semaphore
P is a potentially blocking operation
semaphore_V – “vacates” the semaphore
V should never block
Project 1
Semaphore Internals
What should a semaphore store?
Count
List of threads
TAS lock
Has internal state! However the internal state of
a semaphore should NEVER be made visible to
observers.
Uses TAS locks, however you should omit the
locking in project 1.
Be sure to initialize the semaphore before you
use it.
Project 1
Application
Last part of the project is a simple application
that demonstrates your system components
Free to make this from scratch, but must follow
description in assignment
Should use semaphores, no busy spinning!
Test with different values for N (employees) and
M (customers)
Project 1
Questions
Questions?