|
/**
|
|
* Copyright © 2019, Oracle and/or its affiliates. All rights reserved.
|
|
*
|
|
* Licensed under the Universal Permissive License v 1.0 as shown at
|
|
* http://oss.oracle.com/licenses/upl
|
|
*
|
|
*/
|
|
#include "sched.h"
|
|
#include "malloc.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include "common/spew.h"
|
|
|
|
// Fib example
|
|
|
|
magic_t pfib_magic = "pfib magic";
|
|
struct pfib_frame {
|
|
magic_t *magic;
|
|
size_t n;
|
|
size_t sum;
|
|
};
|
|
static struct pfib_frame *make_pfib_frame(size_t n) {
|
|
struct pfib_frame *MALLOC(result);
|
|
*result = (struct pfib_frame){.magic = &pfib_magic,
|
|
.n = n,
|
|
.sum = 0};
|
|
spew(SPEW_DEBUG, "%p n=%lu", result, result->n);
|
|
return result;
|
|
}
|
|
static struct pfib_frame *cast_pfib_frame(void *af) {
|
|
assert(af);
|
|
struct pfib_frame *pf = af;
|
|
assert(pf->magic == &pfib_magic);
|
|
return pf;
|
|
}
|
|
struct frame *pfib(struct frame *frame, void *app_frame);
|
|
static struct frame *pfib2(struct frame *frame, void *app_frame);
|
|
static struct frame *pfib3(struct frame *frame, void *app_frame);
|
|
static struct frame *pfib4(struct frame *frame, void *app_frame);
|
|
static void pfib_return_inlet(void *parent_app_frame, size_t result) {
|
|
struct pfib_frame *pf = cast_pfib_frame(parent_app_frame);
|
|
pf->sum += result;
|
|
}
|
|
struct frame *pfib(struct frame *frame, void *app_frame) {
|
|
struct pfib_frame *f = cast_pfib_frame(app_frame);
|
|
spew(SPEW_DEBUG, "fib(%lu)", f->n);
|
|
if (f->n < 2) {
|
|
//sleep((unsigned int)f->n);
|
|
size_t r = f->n;
|
|
free(f);
|
|
return sched_return(frame, r);
|
|
} else {
|
|
struct pfib_frame *subf = make_pfib_frame(f->n-1);
|
|
return pfib(sched_spawn(frame, pfib2, subf, pfib_return_inlet), subf);
|
|
}
|
|
}
|
|
static struct frame *pfib2(struct frame *frame, void *app_frame) {
|
|
struct pfib_frame *f = cast_pfib_frame(app_frame);
|
|
struct pfib_frame *subf = make_pfib_frame(f->n-2);
|
|
return pfib(sched_spawn(frame, pfib3, subf, pfib_return_inlet), subf);
|
|
}
|
|
static struct frame *pfib3(struct frame *frame, void *app_frame __attribute__((unused))) {
|
|
return sched_sync(frame, pfib4);
|
|
}
|
|
static struct frame *pfib4(struct frame *frame, void *app_frame) {
|
|
struct pfib_frame *f = cast_pfib_frame(app_frame);
|
|
size_t sum = f->sum;
|
|
free(f);
|
|
return sched_return(frame, sum);
|
|
}
|
|
|
|
static size_t fib(size_t n) {
|
|
struct pfib_frame *pf = make_pfib_frame((size_t)n);
|
|
size_t fn = prun(4, pfib, pf);
|
|
return fn;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc == 1) {
|
|
assert(0 == fib(0));
|
|
assert(1 == fib(1));
|
|
assert(1 == fib(2));
|
|
assert(2 == fib(3));
|
|
assert(3 == fib(4));
|
|
assert(5 == fib(5));
|
|
assert(8 == fib(6));
|
|
assert(6765 == fib(20));
|
|
} else {
|
|
int n = atoi(argv[1]);
|
|
printf("fib(%u)=%lu\n", n, fib((size_t)n));
|
|
}
|
|
return 0;
|
|
}
|