00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #ifndef _PHYSICAL_LOG_TORNBIT_H
00086 #define _PHYSICAL_LOG_TORNBIT_H
00087
00088
00089 #include <stdio.h>
00090 #include <stdint.h>
00091 #include <stdbool.h>
00092
00093 #include <result.h>
00094 #include <list.h>
00095 #include "../hal/pcm_i.h"
00096 #include "log_i.h"
00097
00098 uint64_t load_nt_word(void *addr);
00099
00100 #undef _DEBUG_THIS
00101
00102
00103 #ifdef __cplusplus
00104 extern "C" {
00105 #endif
00106
00107
00108 #define CHUNK_SIZE 64
00109
00110
00111 #define TORN_MASK 0x8000000000000000LLU
00112 #define TORN_MASKC 0x7FFFFFFFFFFFFFFFLLU
00113 #define TORNBIT_ZERO 0x0000000000000000LLU
00114 #define TORNBIT_ONE 0x8000000000000000LLU
00115
00116 #define LF_TORNBIT TORN_MASK
00117 #define LF_HEAD_MASK 0x00000000FFFFFFFFLLU
00118
00119
00120
00121 typedef struct m_phlog_tornbit_s m_phlog_tornbit_t;
00122 typedef struct m_phlog_tornbit_nvmd_s m_phlog_tornbit_nvmd_t;
00123
00124 struct m_phlog_tornbit_nvmd_s {
00125 pcm_word_t generic_flags;
00126 pcm_word_t flags;
00127 pcm_word_t reserved3;
00128 pcm_word_t reserved4;
00129 };
00130
00131
00132
00133
00142 struct m_phlog_tornbit_s {
00143 uint64_t buffer[CHUNK_SIZE/sizeof(uint64_t)];
00144 uint64_t buffer_count;
00145 uint64_t write_remainder;
00146 uint64_t write_remainder_nbits;
00147 uint64_t read_remainder;
00148 uint64_t read_remainder_nbits;
00149 uint64_t *nvphlog;
00150 m_phlog_tornbit_nvmd_t *nvmd;
00151 uint64_t head;
00152 uint64_t tail;
00153 uint64_t stable_tail;
00154 uint64_t read_index;
00155 uint64_t tornbit;
00156
00157
00158
00159 uint64_t pad1[8];
00160 uint64_t stat_wait_for_trunc;
00161 uint64_t stat_wait_time_for_trunc;
00162 };
00163
00164
00165 static
00166 void
00167 print_binary64(uint64_t val)
00168 {
00169 int i;
00170 uint64_t mask = 0x8000000000000000LLU;
00171 for (i=0; i<64; i++){
00172 if ((mask & val) > 0)
00173 printf("1");
00174 else
00175 printf("0");
00176 mask >>= 1;
00177 }
00178 }
00179
00180
00187 static inline
00188 void
00189 tornbit_write_buffer2log(pcm_storeset_t *set, m_phlog_tornbit_t *log)
00190 {
00191
00192
00193
00194
00195 #ifdef _DEBUG_THIS
00196 printf("tornbit_write_buffer2log: log->tail = %llu\n", log->tail);
00197 #endif
00198
00199 PCM_SEQSTREAM_STORE_64B_FIRST_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+0)],
00200 log->tornbit | (pcm_word_t) log->buffer[0]);
00201 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+1)],
00202 log->tornbit | (pcm_word_t) log->buffer[1]);
00203 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+2)],
00204 log->tornbit | (pcm_word_t) log->buffer[2]);
00205 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+3)],
00206 log->tornbit | (pcm_word_t) log->buffer[3]);
00207 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+4)],
00208 log->tornbit | (pcm_word_t) log->buffer[4]);
00209 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+5)],
00210 log->tornbit | (pcm_word_t) log->buffer[5]);
00211 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+6)],
00212 log->tornbit | (pcm_word_t) log->buffer[6]);
00213 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+7)],
00214 log->tornbit | (pcm_word_t) log->buffer[7]);
00215
00216 log->buffer_count=0;
00217 log->tail = (log->tail+8) & (PHYSICAL_LOG_NUM_ENTRIES-1);
00218
00219
00220 if (log->tail == 0x0) {
00221 log->tornbit = ~(log->tornbit) & TORN_MASK;
00222 }
00223 }
00224
00225
00233 static inline
00234 m_result_t
00235 m_phlog_tornbit_write(pcm_storeset_t *set, m_phlog_tornbit_t *log, pcm_word_t value)
00236 {
00237
00238
00239
00240
00241
00242
00243
00244
00245 #ifdef _DEBUG_THIS
00246 printf("buffer_count = %lu, write_remainder_nbits = %lu, log->head=%lu, log->tail=%lu\n", log->buffer_count, log->write_remainder_nbits, log->head, log->tail);
00247 printf("value = 0x%llX\n", value);
00248 printf("[T: %x] &log->tail= %p\n", pthread_self(), &log->tail);
00249 #endif
00250
00251 if (log->buffer_count+1 > CHUNK_SIZE/sizeof(pcm_word_t)-1) {
00252
00253
00254 if (((log->tail + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1))
00255 == log->head)
00256 {
00257 #ifdef _DEBUG_THIS
00258 printf("LOG OVERFLOW!!!\n");
00259 printf("tail: %lu\n", log->tail);
00260 printf("head: %lu\n", log->head);
00261 #endif
00262 return M_R_FAILURE;
00263 } else {
00264 #ifdef _DEBUG_THIS
00265 printf("FLUSH BUFFER OUT\n");
00266 #endif
00267 log->buffer[log->buffer_count] = ~TORN_MASK &
00268 (log->write_remainder |
00269 (value << log->write_remainder_nbits));
00270
00271 log->write_remainder = value >> (64 - (log->write_remainder_nbits+1));
00272 log->write_remainder_nbits = (log->write_remainder_nbits + 1) & (64 - 1);
00273
00274
00275 tornbit_write_buffer2log(set, log);
00276
00277
00278
00279
00280
00281 if (log->write_remainder_nbits == 0) {
00282 log->buffer[0] = ~TORN_MASK &
00283 (log->write_remainder);
00284 log->buffer_count++;
00285
00286
00287 log->write_remainder = log->write_remainder >> 63;
00288 log->write_remainder_nbits = 1;
00289 }
00290 }
00291 } else {
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 log->buffer[log->buffer_count] = ~TORN_MASK &
00304 (log->write_remainder |
00305 (value << log->write_remainder_nbits));
00306
00307
00308
00309
00310 log->write_remainder_nbits = (log->write_remainder_nbits + 1) & (64 - 1);
00311 log->write_remainder = value >> (64 - log->write_remainder_nbits);
00312 log->buffer_count++;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 }
00323 return M_R_SUCCESS;
00324 }
00325
00326
00334 static inline
00335 m_result_t
00336 m_phlog_tornbit_flush(pcm_storeset_t *set, m_phlog_tornbit_t *log)
00337 {
00338 #ifdef _DEBUG_THIS
00339 printf("m_phlog_flush\n");
00340 printf("nvmd : %p\n", log->nvmd);
00341 printf("nvphlog : %p\n", log->nvphlog);
00342 #endif
00343 if (log->write_remainder_nbits > 0) {
00344
00345 if (((log->tail + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1))
00346 == log->head)
00347 {
00348 #ifdef _DEBUG_THIS
00349 printf("FLUSH: LOG OVERFLOW!!!\n");
00350 printf("tail: %lu\n", log->tail);
00351 printf("head: %lu\n", log->head);
00352 printf("stable_tail: %lu\n", log->stable_tail);
00353 #endif
00354 return M_R_FAILURE;
00355 } else {
00356
00357
00358
00359
00360
00361
00362
00363 log->buffer[log->buffer_count] = ~TORN_MASK &
00364 (log->write_remainder);
00365 log->buffer_count++;
00366 log->write_remainder_nbits = 0;
00367 log->write_remainder = 0;
00368
00369
00370
00371
00372
00373 tornbit_write_buffer2log(set, log);
00374 }
00375 }
00376 log->stable_tail = log->tail;
00377 PCM_SEQSTREAM_FLUSH(set);
00378 #ifdef _DEBUG_THIS
00379 printf("phlog_tornbit_flush: log->tail = %llu, log->stable_tail = %llu\n", log->tail, log->stable_tail);
00380 #endif
00381 return M_R_SUCCESS;
00382 }
00383
00384
00391 #if 0
00392 static inline
00393 m_result_t
00394 m_phlog_tornbit_read(m_phlog_tornbit_t *log, uint64_t *valuep)
00395 {
00396 uint64_t value;
00397
00398 #ifdef _DEBUG_THIS
00399 printf("log_read: %lu %lu %lu\n", log->read_index, (uint64_t) log->read_remainder_nbits, log->stable_tail);
00400 #endif
00401
00402 if (log->read_index != log->stable_tail &&
00403 log->read_index + 1 != log->stable_tail)
00404 {
00405 #ifdef _DEBUG_THIS
00406 printf("[%04lu]: 0x%016llX\n", log->read_index, ~TORN_MASK & log->nvphlog[log->read_index]);
00407 #endif
00408 value = (~TORN_MASK & log->nvphlog[log->read_index]) >> log->read_remainder_nbits;
00409 log->read_index = (log->read_index + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00410 #ifdef _DEBUG_THIS
00411 printf("[%04lu]: 0x%016llX\n", log->read_index, ~TORN_MASK & log->nvphlog[log->read_index]);
00412 #endif
00413 value |= log->nvphlog[log->read_index] << (63 - log->read_remainder_nbits);
00414 log->read_remainder_nbits = (log->read_remainder_nbits + 1) & (64 - 1);
00415 if (log->read_remainder_nbits == 63) {
00416 log->read_index = (log->read_index + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00417 log->read_remainder_nbits = 0;
00418 }
00419 *valuep = value;
00420 #ifdef _DEBUG_THIS
00421 printf("\t read value: 0x%016lX\n", value);
00422 #endif
00423 return M_R_SUCCESS;
00424 }
00425 #ifdef _DEBUG_THIS
00426 printf("NO DATA\n");
00427 #endif
00428 return M_R_FAILURE;
00429 }
00430 #else
00431
00432 static inline
00433 m_result_t
00434 m_phlog_tornbit_read(m_phlog_tornbit_t *log, uint64_t *valuep)
00435 {
00436 uint64_t value;
00437 uint64_t tmp;
00438
00439 #ifdef _DEBUG_THIS
00440 printf("log_read: %lu %lu %lu\n", log->read_index, (uint64_t) log->read_remainder_nbits, log->stable_tail);
00441 #endif
00442
00443 if (log->read_index != log->stable_tail &&
00444 log->read_index + 1 != log->stable_tail)
00445 {
00446 #ifdef _DEBUG_THIS
00447 printf("[%04lu]: 0x%016llX\n", log->read_index, ~TORN_MASK & log->nvphlog[log->read_index]);
00448 #endif
00449 tmp = load_nt_word(&log->nvphlog[log->read_index]);
00450 value = (~TORN_MASK & tmp) >> log->read_remainder_nbits;
00451 log->read_index = (log->read_index + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00452 #ifdef _DEBUG_THIS
00453 printf("[%04lu]: 0x%016llX\n", log->read_index, ~TORN_MASK & log->nvphlog[log->read_index]);
00454 #endif
00455 tmp = load_nt_word(&log->nvphlog[log->read_index]);
00456 value |= tmp << (63 - log->read_remainder_nbits);
00457 log->read_remainder_nbits = (log->read_remainder_nbits + 1) & (64 - 1);
00458 if (log->read_remainder_nbits == 63) {
00459 log->read_index = (log->read_index + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00460 log->read_remainder_nbits = 0;
00461 }
00462 *valuep = value;
00463 #ifdef _DEBUG_THIS
00464 printf("\t read value: 0x%016lX\n", value);
00465 #endif
00466 return M_R_SUCCESS;
00467 }
00468 #ifdef _DEBUG_THIS
00469 printf("NO DATA\n");
00470 #endif
00471 return M_R_FAILURE;
00472 }
00473 #endif
00474
00481 static inline
00482 bool
00483 m_phlog_tornbit_stable_exists(m_phlog_tornbit_t *log)
00484 {
00485 if (log->read_index != log->stable_tail) {
00486 return true;
00487 }
00488 return false;
00489 }
00490
00491
00492
00498 static inline
00499 void
00500 m_phlog_tornbit_next_chunk(m_phlog_tornbit_t *log)
00501 {
00502 uint64_t read_index;
00503
00504 if (log->read_remainder_nbits > 0) {
00505 log->read_remainder_nbits = 0;
00506 read_index = log->read_index & ~(CHUNK_SIZE/sizeof(pcm_word_t) - 1);
00507 log->read_index = (read_index + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1);
00508 } else {
00509 log->read_remainder_nbits = 0;
00510 read_index = log->read_index & ~(CHUNK_SIZE/sizeof(pcm_word_t) - 1);
00511
00512
00513
00514
00515 if (read_index != log->read_index) {
00516 log->read_index = (read_index + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1);
00517 }
00518 }
00519 }
00520
00521
00528 static inline
00529 m_result_t
00530 m_phlog_tornbit_checkpoint_readindex(m_phlog_tornbit_t *log, uint64_t *readindex)
00531 {
00532 if (log->read_remainder_nbits > 0) {
00533 return M_R_FAILURE;
00534 }
00535 *readindex = log->read_index;
00536
00537 return M_R_SUCCESS;
00538 }
00539
00540
00547 static inline
00548 void
00549 m_phlog_tornbit_restore_readindex(m_phlog_tornbit_t *log, uint64_t readindex)
00550 {
00551 log->read_index = readindex;
00552 log->read_remainder_nbits = 0;
00553 }
00554
00555
00556 static inline
00557 m_result_t
00558 m_phlog_tornbit_truncate_sync(pcm_storeset_t *set, m_phlog_tornbit_t *phlog)
00559 {
00560 phlog->head = phlog->tail;
00561
00562
00563 PCM_NT_STORE(set, (volatile pcm_word_t *) &phlog->nvmd->flags, (pcm_word_t) (phlog->head | phlog->tornbit));
00564 PCM_NT_FLUSH(set);
00565
00566 return M_R_SUCCESS;
00567 }
00568
00569 m_result_t m_phlog_tornbit_format (pcm_storeset_t *set, m_phlog_tornbit_nvmd_t *nvmd, pcm_word_t *nvphlog, int type);
00570 m_result_t m_phlog_tornbit_alloc (m_phlog_tornbit_t **phlog_tornbitp);
00571 m_result_t m_phlog_tornbit_init (m_phlog_tornbit_t *phlog, m_phlog_tornbit_nvmd_t *nvmd, pcm_word_t *nvphlog);
00572 m_result_t m_phlog_tornbit_check_consistency(m_phlog_tornbit_nvmd_t *nvmd, pcm_word_t *nvphlog, uint64_t *stable_tail);
00573 m_result_t m_phlog_tornbit_prepare_truncate(m_log_dsc_t *log_dsc);
00574 m_result_t m_phlog_tornbit_truncate_async(pcm_storeset_t *set, m_phlog_tornbit_t *phlog);
00575
00576
00577 #ifdef __cplusplus
00578 }
00579 #endif
00580
00581 #endif