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
00059 #ifndef _PHYSICAL_LOG_BASE_H
00060 #define _PHYSICAL_LOG_BASE_H
00061
00062
00063 #include <stdio.h>
00064 #include <stdint.h>
00065 #include <stdbool.h>
00066
00067 #include <result.h>
00068 #include <list.h>
00069 #include "../hal/pcm_i.h"
00070 #include "log_i.h"
00071
00072
00073 #ifdef __cplusplus
00074 extern "C" {
00075 #endif
00076
00077
00078 #define CHUNK_SIZE 64
00079
00080
00081 typedef struct m_phlog_base_s m_phlog_base_t;
00082 typedef struct m_phlog_base_nvmd_s m_phlog_base_nvmd_t;
00083
00084 struct m_phlog_base_nvmd_s {
00085 pcm_word_t generic_flags;
00086 pcm_word_t head;
00087 pcm_word_t tail;
00088 pcm_word_t reserved4;
00089 };
00090
00091
00092
00093
00102 struct m_phlog_base_s {
00103 uint64_t buffer[CHUNK_SIZE/sizeof(uint64_t)];
00104 uint64_t buffer_count;
00105 uint64_t *nvphlog;
00106 m_phlog_base_nvmd_t *nvmd;
00107 uint64_t head;
00108 uint64_t tail;
00109 uint64_t read_index;
00110
00111
00112 uint64_t pad1[8];
00113 uint64_t stat_wait_for_trunc;
00114 uint64_t stat_wait_time_for_trunc;
00115 };
00116
00117
00118
00125 static inline
00126 void
00127 base_write_buffer2log(pcm_storeset_t *set, m_phlog_base_t *log)
00128 {
00129
00130
00131
00132
00133 PCM_SEQSTREAM_STORE_64B_FIRST_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+0)],
00134 (pcm_word_t) log->buffer[0]);
00135 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+1)],
00136 (pcm_word_t) log->buffer[1]);
00137 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+2)],
00138 (pcm_word_t) log->buffer[2]);
00139 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+3)],
00140 (pcm_word_t) log->buffer[3]);
00141 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+4)],
00142 (pcm_word_t) log->buffer[4]);
00143 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+5)],
00144 (pcm_word_t) log->buffer[5]);
00145 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+6)],
00146 (pcm_word_t) log->buffer[6]);
00147 PCM_SEQSTREAM_STORE_64B_NEXT_WORD(set, (volatile pcm_word_t *) &log->nvphlog[(log->tail+7)],
00148 (pcm_word_t) log->buffer[7]);
00149 log->buffer_count=0;
00150 log->tail = (log->tail+8) & (PHYSICAL_LOG_NUM_ENTRIES-1);
00151 }
00152
00153
00161 static inline
00162 m_result_t
00163 m_phlog_base_write(pcm_storeset_t *set, m_phlog_base_t *log, pcm_word_t value)
00164 {
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 if (log->buffer_count+1 > CHUNK_SIZE/sizeof(pcm_word_t)-1) {
00175
00176 if (((log->tail + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1))
00177 == log->head)
00178 {
00179 return M_R_FAILURE;
00180 } else {
00181 log->buffer[log->buffer_count] = value;
00182 log->buffer_count++;
00183 base_write_buffer2log(set, log);
00184 }
00185 } else {
00186 log->buffer[log->buffer_count] = value;
00187 log->buffer_count++;
00188 }
00189
00190 return M_R_SUCCESS;
00191 }
00192
00193
00201 static inline
00202 m_result_t
00203 m_phlog_base_flush(pcm_storeset_t *set, m_phlog_base_t *log)
00204 {
00205 if (log->buffer_count > 0) {
00206 base_write_buffer2log(set, log);
00207 }
00208 PCM_SEQSTREAM_FLUSH(set);
00209 PCM_NT_STORE(set, (volatile pcm_word_t *) &log->nvmd->tail,
00210 (pcm_word_t) log->tail);
00211 PCM_NT_FLUSH(set);
00212
00213 return M_R_SUCCESS;
00214 }
00215
00216
00223 static inline
00224 m_result_t
00225 m_phlog_base_read(m_phlog_base_t *log, uint64_t *valuep)
00226 {
00227 uint64_t value;
00228
00229
00230 if (log->read_index != log->nvmd->tail) {
00231 value = log->nvphlog[log->read_index];
00232 log->read_index = (log->read_index + 1) & (PHYSICAL_LOG_NUM_ENTRIES - 1);
00233 *valuep = value;
00234 return M_R_SUCCESS;
00235 }
00236 return M_R_FAILURE;
00237 }
00238
00239
00246 static inline
00247 bool
00248 m_phlog_base_stable_exists(m_phlog_base_t *log)
00249 {
00250 if (log->read_index != log->nvmd->tail) {
00251 return true;
00252 }
00253 return false;
00254 }
00255
00256
00257
00263 static inline
00264 void
00265 m_phlog_base_next_chunk(m_phlog_base_t *log)
00266 {
00267 uint64_t read_index;
00268
00269 read_index = log->read_index & ~(CHUNK_SIZE/sizeof(pcm_word_t) - 1);
00270
00271
00272
00273
00274 if (read_index != log->read_index) {
00275 log->read_index = (read_index + CHUNK_SIZE/sizeof(pcm_word_t)) & (PHYSICAL_LOG_NUM_ENTRIES-1);
00276 }
00277 }
00278
00279
00286 static inline
00287 m_result_t
00288 m_phlog_base_checkpoint_readindex(m_phlog_base_t *log, uint64_t *readindex)
00289 {
00290 *readindex = log->read_index;
00291
00292 return M_R_SUCCESS;
00293 }
00294
00295
00302 static inline
00303 void
00304 m_phlog_base_restore_readindex(m_phlog_base_t *log, uint64_t readindex)
00305 {
00306 log->read_index = readindex;
00307 }
00308
00309
00310 static inline
00311 m_result_t
00312 m_phlog_base_truncate_sync(pcm_storeset_t *set, m_phlog_base_t *phlog)
00313 {
00314 phlog->head = phlog->tail;
00315
00316 PCM_NT_STORE(set, (volatile pcm_word_t *) &phlog->nvmd->head,
00317 (pcm_word_t) phlog->head);
00318 PCM_NT_FLUSH(set);
00319
00320 return M_R_SUCCESS;
00321 }
00322
00323
00324 m_result_t m_phlog_base_format (pcm_storeset_t *set, m_phlog_base_nvmd_t *nvmd, pcm_word_t *nvphlog, int type);
00325 m_result_t m_phlog_base_alloc (m_phlog_base_t **phlog_basep);
00326 m_result_t m_phlog_base_init (m_phlog_base_t *phlog, m_phlog_base_nvmd_t *nvmd, pcm_word_t *nvphlog);
00327 m_result_t m_phlog_base_check_consistency(m_phlog_base_nvmd_t *nvmd, pcm_word_t *nvphlog, uint64_t *stable_tail);
00328 m_result_t m_phlog_base_truncate_async(pcm_storeset_t *set, m_phlog_base_t *phlog);
00329
00330
00331 #ifdef __cplusplus
00332 }
00333 #endif
00334
00335 #endif