resource.c 3.46 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Copyright (C) 2014 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
*/

#include "codes/resource.h"
#include <assert.h>
9
#include <string.h>
10
#include <stdio.h>
11 12 13 14

static uint64_t min_u64(uint64_t a, uint64_t b){
    return a < b ? a : b;
}
15 16 17 18

/* initialize with avail capacity, all unreserved */
void resource_init(uint64_t avail, resource *r){
    r->num_tokens = 0;
19 20 21
    r->max_all  = avail;
    r->avail[0] = avail;
    r->max[0] = avail;
22
    r->min_avail[0] = avail;
23 24 25
    for (int i = 1; i < MAX_RESERVE; i++){
        r->avail[i] = 0;
        r->max[i] = 0;
26
        r->min_avail[i] = 0;
27
    }
28 29
}

30 31
/* Acquire req units of the resource. 
 * Returns 0 on success, 1 on failure (not enough available), 2 on invalid
32
 * token -1 on a request that cannot be satisfied. */
33 34 35 36 37
int resource_get(uint64_t req, resource_token_t tok, resource *r){
    if (tok > r->num_tokens){ 
        return 2;
    }
    else if (req > r->avail[tok]){
38 39
        return 1;
    }
40 41 42
    else if (req > r->max[tok]) {
        return -1;
    }
43
    else{
44
        r->avail[tok] -= req;
45
        r->min_avail[tok] = min_u64(r->avail[tok], r->min_avail[tok]);
46 47 48 49
        return 0;
    }
}

50 51 52 53 54 55 56 57
/* Release req units of the resource.
 * Returns 0 on success, 2 on invalid token */
int resource_free(uint64_t req, resource_token_t tok, resource *r){
    if (tok > r->num_tokens){ 
        return 2;
    }
    else{
        r->avail[tok] += req;
58
        // TODO: check for invalid state? (more available than possible)
59 60
        return 0;
    }
61 62
}

63 64 65 66 67 68 69
/* Determine amount of resource units remaining
 * Returns 0 on success, 2 on invalid token */
int resource_get_avail(resource_token_t tok, uint64_t *avail, resource *r){
    if (tok > r->num_tokens){
        return 2;
    }
    else{
70 71
        *avail = r->avail[tok];
	return 0;
72 73 74 75 76 77 78 79 80 81 82
    }
}

/* Determine amount of used resource units.
 * The number returned is based on the pool-specific maximums, for which
 * reserve calls can change */
int resource_get_used(resource_token_t tok, uint64_t *used, resource *r){
    if (tok > r->num_tokens){
        return 2;
    }
    else{
83 84
        *used = r->max[tok] - r->avail[tok];
	return 0;
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    }
}

/* Get and restore minimum stat (support for RC). So that the resource
 * interface doesn't need to upgrade to a full LP, store stats in
 * caller-provided arguments. */
int resource_get_min_avail(resource_token_t tok, uint64_t *min_avail,
        resource *r){
    if (tok > r->num_tokens){
        return 2;
    }
    else{
        *min_avail = r->min_avail[tok];
        return 0;
    }
}
int resource_restore_min_avail(resource_token_t tok, uint64_t min_avail,
        resource *r){
    if (tok > r->num_tokens){
        return 2;
    }
    else{
        r->min_avail[tok] = min_avail;
        return 0;
    }
}

/* Reservation function, same return values as get. 
113 114 115 116
 * These functions expect exactly one caller per LP group as 
 * defined by the codes configuration 
 * TODO: "un-reserving" not yet supported */
int resource_reserve(uint64_t req, resource_token_t *tok, resource *r){
117 118 119 120
    if (r->num_tokens > MAX_RESERVE){
        return 2;
    }
    else if (req > r->avail[0]){
121 122 123
        return 1;
    }
    else{
124 125 126
        /* reserved tokens start from 1 */ 
        *tok = ++(r->num_tokens);
        r->avail[*tok] = req;
127
        r->max[*tok] = req;
128
        r->min_avail[*tok] = req;
129 130
        r->max[0] -= req;
        r->avail[0] -= req;
131 132 133 134 135 136 137 138 139 140 141 142
        return 0;
    }
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ts=8 sts=4 sw=4 expandtab
 */