Operating System代写:CS281 Development of Nonlocal Jump Functions

代写OS中Jump类方法中的setjmp()和longjmp(),这两个函数一般用于try-catch块的异常处理。

Overview

In this project, you will write the code of two C functions called setjmp() and longjmp() which allow a program to transfer control directly from one function to another without returning to the function that called them. These two functions are available in the standard
C library but here you will write your own version.

Introduction

Note: The following description of the setjmp() and longjmp() behavior is taken from
Section 8.6, Nonlocal Jumps, of the textbook “Computer systems : a programmer’s perspective” by Bryant and O’Hallaron, 2nd edition (which we use in CS 283).
C provides a form of user-level exceptional control flow, called a nonlocal jump, that transfers control directly from one function to another currently executing function without having to go through the normal call-and-return sequence. Nonlocal jumps are provided by the setjmp and longjmp functions.

When called directly, the setjmp function saves the current calling environment in the env buffer, for later use by longjmp, and returns a 0. The calling environment includes the program counter, stack pointer, and general purpose registers.
The longjmp function restores the calling environment from the env buffer and then triggers a return from the most recent setjmp call that initialized env. The setjmp then returns with the nonzero return value retval.
Notice that

  1. the setjmp function is called once, but returns multiple times:
    • a. once when the setjmp is first called and the calling environment is stored in the env buffer, and
    • b. once for each corresponding longjmp call
  2. the longjmp function is called once, but never returns

An important application of nonlocal jumps is to permit an immediate return from a deeply nested function call, usually as a result of detecting some error condition. If an error condition is detected deep in a nested function call, we can use a nonlocal jump to return directly to a common localized error handler instead of laboriously unwinding the call stack.
Figure 8.39 shows an example of how this might work. The main routine first calls setjmp to save the current calling environment, and then calls function foo, which in turn calls function bar. If foo or bar encounter an error, they return immediately from the setjmp via a longjmp call. The nonzero return value of the setjmp indicates the error type, which can then be decoded and handled in one place in the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// This is Figure 8.39, Nonlocal jump example.
// This example shows the framework for using nonlocal jumps
// to recover from error conditions in deeply nested
// functions without having to unwind the entire stack.
// The code can be found in code/ecf/setjmp.c

jmp_buf buf;

int error1 = 0;
int error2 = 1;

void foo(void), bar(void);
int main()
{
int rc;
rc = setjmp(buf);
if (rc == 0) foo();
else if (rc == 1)
printf("Detected an error1 condition in foo\n");
else if (rc == 2)
printf("Detected an error2 condition in foo\n");
else
printf("Unknown error condition in foo\n");
exit(0);
}

/* Deeply nested function foo */
void foo(void)
{
if (error1)
longjmp(buf, 1);
bar();
}

void bar(void)
{
if (error2)
longjmp(buf, 2);
}

What to Do

Write the code for the two functions setjmp() and longjmp(). The code will provide smaller functionality than the C library version and will simply work correctly in the program shown below.
The only requirement is that when main () calls fun1() and fun1() calls fun2(), if fun2() calls longjmp() - as it does in the example below - then fun2() does not return to fun1() but instead setjmp() returns to main() with return value equal to 1.

Start working on the project immediately after completing G2, the Programming Assignment 2, which asks you to analyze the use of the stack in C programs.

The C compiler includes a call to __main, so we need to supply an empty function
__main() to stop the SPIM simulator from complaining about an unresolved symbol. The call to dummy(), another empty function, is necessary to force the compiler to treat the calling function as a non-leaf function and produce all the instructions that create a full frame in the stack. The code of the other functions should be self-explanatory, except for print_hex () and print_str (). Use these two functions as tools to print numbers and strings on the SPIM simulator. Students who want to understand the workings of these two functions should contact me for additional documentation.
What To Hand In

  • A text file with all C code including the two functions setjmp() and longjmp().
  • Screenshots of the SPIM simulator windows demonstrating that your program is working correctly.