]>
Commit | Line | Data |
---|---|---|
548de42e AP |
1 | /********************************************************************** |
2 | * Copyright (c) 2017 Andrew Poelstra * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
6 | ||
7 | #ifndef _SECP256K1_SCRATCH_IMPL_H_ | |
8 | #define _SECP256K1_SCRATCH_IMPL_H_ | |
9 | ||
10 | #include "scratch.h" | |
11 | ||
12 | /* Using 16 bytes alignment because common architectures never have alignment | |
13 | * requirements above 8 for any of the types we care about. In addition we | |
14 | * leave some room because currently we don't care about a few bytes. | |
15 | * TODO: Determine this at configure time. */ | |
16 | #define ALIGNMENT 16 | |
17 | ||
6fe50439 | 18 | static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size) { |
548de42e AP |
19 | secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret)); |
20 | if (ret != NULL) { | |
6fe50439 | 21 | memset(ret, 0, sizeof(*ret)); |
548de42e AP |
22 | ret->max_size = max_size; |
23 | ret->error_callback = error_callback; | |
24 | } | |
25 | return ret; | |
26 | } | |
27 | ||
28 | static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) { | |
29 | if (scratch != NULL) { | |
6fe50439 | 30 | VERIFY_CHECK(scratch->frame == 0); |
548de42e AP |
31 | free(scratch); |
32 | } | |
33 | } | |
34 | ||
35 | static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) { | |
6fe50439 AP |
36 | size_t i = 0; |
37 | size_t allocated = 0; | |
38 | for (i = 0; i < scratch->frame; i++) { | |
39 | allocated += scratch->frame_size[i]; | |
40 | } | |
41 | if (scratch->max_size - allocated <= objects * ALIGNMENT) { | |
548de42e AP |
42 | return 0; |
43 | } | |
6fe50439 | 44 | return scratch->max_size - allocated - objects * ALIGNMENT; |
548de42e AP |
45 | } |
46 | ||
6fe50439 AP |
47 | static int secp256k1_scratch_allocate_frame(secp256k1_scratch* scratch, size_t n, size_t objects) { |
48 | VERIFY_CHECK(scratch->frame < SECP256K1_SCRATCH_MAX_FRAMES); | |
49 | ||
50 | if (n <= secp256k1_scratch_max_allocation(scratch, objects)) { | |
51 | n += objects * ALIGNMENT; | |
52 | scratch->data[scratch->frame] = checked_malloc(scratch->error_callback, n); | |
53 | if (scratch->data[scratch->frame] == NULL) { | |
548de42e AP |
54 | return 0; |
55 | } | |
6fe50439 AP |
56 | scratch->frame_size[scratch->frame] = n; |
57 | scratch->offset[scratch->frame] = 0; | |
58 | scratch->frame++; | |
59 | return 1; | |
60 | } else { | |
61 | return 0; | |
548de42e | 62 | } |
6fe50439 AP |
63 | } |
64 | ||
65 | static void secp256k1_scratch_deallocate_frame(secp256k1_scratch* scratch) { | |
66 | VERIFY_CHECK(scratch->frame > 0); | |
67 | scratch->frame -= 1; | |
68 | free(scratch->data[scratch->frame]); | |
548de42e AP |
69 | } |
70 | ||
71 | static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) { | |
72 | void *ret; | |
6fe50439 | 73 | size_t frame = scratch->frame - 1; |
548de42e | 74 | size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; |
6fe50439 AP |
75 | |
76 | if (scratch->frame == 0 || size + scratch->offset[frame] > scratch->frame_size[frame]) { | |
548de42e AP |
77 | return NULL; |
78 | } | |
6fe50439 | 79 | ret = (void *) ((unsigned char *) scratch->data[frame] + scratch->offset[frame]); |
548de42e | 80 | memset(ret, 0, size); |
6fe50439 | 81 | scratch->offset[frame] += size; |
548de42e | 82 | |
6fe50439 | 83 | return ret; |
548de42e AP |
84 | } |
85 | ||
86 | #endif |