1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#pragma once
40
41#include "toku_config.h"
42
43// Percona portability layer
44
45#if defined(__clang__)
46# define constexpr_static_assert(a, b)
47#else
48# define constexpr_static_assert(a, b) static_assert(a, b)
49#endif
50
51#if defined(_MSC_VER)
52# error "Windows is not supported."
53#endif
54
55#define DEV_NULL_FILE "/dev/null"
56
57#include <my_global.h>
58
59// include here, before they get deprecated
60#include <toku_atomic.h>
61
62#if defined(__GNUC__)
63// GCC linux
64
65#define DO_GCC_PRAGMA(x) _Pragma (#x)
66
67#include <toku_stdint.h>
68#include <unistd.h>
69#include <sys/types.h>
70#include <sys/time.h>
71#include <sys/stat.h>
72#include <stdio.h>
73
74#if defined(__FreeBSD__)
75#include <stdarg.h>
76#endif
77
78#if defined(HAVE_ALLOCA_H)
79# include <alloca.h>
80#endif
81
82#if defined(__cplusplus)
83# include <type_traits>
84#endif
85
86#if defined(__cplusplus)
87# define cast_to_typeof(v) (decltype(v))
88#else
89# define cast_to_typeof(v) (__typeof__(v))
90#endif
91
92#else // __GNUC__ was not defined, so...
93# error "Must use a GNUC-compatible compiler."
94#endif
95
96// Define some constants for Yama in case the build-machine's software is too old.
97#if !defined(HAVE_PR_SET_PTRACER)
98/*
99 * Set specific pid that is allowed to ptrace the current task.
100 * A value of 0 mean "no process".
101 */
102// Well defined ("Yama" in ascii)
103#define PR_SET_PTRACER 0x59616d61
104#endif
105#if !defined(HAVE_PR_SET_PTRACER_ANY)
106#define PR_SET_PTRACER_ANY ((unsigned long)-1)
107#endif
108
109#if defined(__cplusplus)
110// decltype() here gives a reference-to-pointer instead of just a pointer,
111// just use __typeof__
112# define CAST_FROM_VOIDP(name, value) name = static_cast<__typeof__(name)>(value)
113#else
114# define CAST_FROM_VOIDP(name, value) name = cast_to_typeof(name) (value)
115#endif
116
117#ifndef TOKU_OFF_T_DEFINED
118#define TOKU_OFF_T_DEFINED
119typedef int64_t toku_off_t;
120#endif
121
122#include "toku_os.h"
123#include "toku_htod.h"
124#include "toku_assert.h"
125#include "toku_crash.h"
126#include "toku_debug_sync.h"
127
128#define UU(x) x __attribute__((__unused__))
129
130// Branch prediction macros.
131// If supported by the compiler, will hint in inctruction caching for likely
132// branching. Should only be used where there is a very good idea of the correct
133// branch heuristics as determined by profiling. Mostly copied from InnoDB.
134// Use:
135// "if (FT_LIKELY(x))" where the chances of "x" evaluating true are higher
136// "if (FT_UNLIKELY(x))" where the chances of "x" evaluating false are higher
137#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(__INTEL_COMPILER)
138
139// Tell the compiler that 'expr' probably evaluates to 'constant'.
140#define FT_EXPECT(expr, constant) __builtin_expect(expr, constant)
141
142#else
143
144#warning "No FT branch prediction operations in use!"
145#define FT_EXPECT(expr, constant) (expr)
146
147#endif // defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
148
149// Tell the compiler that cond is likely to hold
150#define FT_LIKELY(cond) FT_EXPECT(bool(cond), true)
151
152// Tell the compiler that cond is unlikely to hold
153#define FT_UNLIKELY(cond) FT_EXPECT(bool(cond), false)
154
155#include "toku_instrumentation.h"
156
157#if defined(__cplusplus)
158extern "C" {
159#endif
160
161// Deprecated functions.
162#if !defined(TOKU_ALLOW_DEPRECATED) && !defined(__clang__)
163int creat(const char *pathname, mode_t mode) __attribute__((__deprecated__));
164int fstat(int fd, struct stat *buf) __attribute__((__deprecated__));
165int stat(const char *path, struct stat *buf) __attribute__((__deprecated__));
166int getpid(void) __attribute__((__deprecated__));
167# if defined(__FreeBSD__) || defined(__APPLE__)
168int syscall(int __sysno, ...) __attribute__((__deprecated__));
169# else
170long int syscall(long int __sysno, ...) __attribute__((__deprecated__));
171# endif
172 long int sysconf(int) __attribute__((__deprecated__));
173int mkdir(const char *pathname, mode_t mode) __attribute__((__deprecated__));
174int dup2(int fd, int fd2) __attribute__((__deprecated__));
175int _dup2(int fd, int fd2) __attribute__((__deprecated__));
176// strdup is a macro in some libraries.
177#undef strdup
178# if defined(__FreeBSD__)
179char* strdup(const char *) __malloc_like __attribute__((__deprecated__));
180# elif defined(__APPLE__)
181char* strdup(const char *) __attribute__((__deprecated__));
182# else
183char* strdup(const char *) __THROW __attribute_malloc__ __nonnull ((1)) __attribute__((__deprecated__));
184# endif
185#undef __strdup
186char* __strdup(const char *) __attribute__((__deprecated__));
187# ifndef DONT_DEPRECATE_WRITES
188ssize_t write(int, const void *, size_t) __attribute__((__deprecated__));
189ssize_t pwrite(int, const void *, size_t, off_t) __attribute__((__deprecated__));
190#endif
191# ifndef DONT_DEPRECATE_MALLOC
192# if defined(__FreeBSD__)
193extern void *malloc(size_t) __malloc_like __attribute__((__deprecated__));
194extern void free(void*) __attribute__((__deprecated__));
195extern void *realloc(void*, size_t) __malloc_like __attribute__((__deprecated__));
196# elif defined(__APPLE__)
197extern void *malloc(size_t) __attribute__((__deprecated__));
198extern void free(void*) __attribute__((__deprecated__));
199extern void *realloc(void*, size_t) __attribute__((__deprecated__));
200# else
201extern void *malloc(size_t) __THROW __attribute__((__deprecated__));
202extern void free(void*) __THROW __attribute__((__deprecated__));
203extern void *realloc(void*, size_t) __THROW __attribute__((__deprecated__));
204# endif
205# endif
206# ifndef DONT_DEPRECATE_ERRNO
207//extern int errno __attribute__((__deprecated__));
208# endif
209#if !defined(__APPLE__)
210// Darwin headers use these types, we should not poison them
211#undef TRUE
212#undef FALSE
213# pragma GCC poison u_int8_t
214# pragma GCC poison u_int16_t
215# pragma GCC poison u_int32_t
216# pragma GCC poison u_int64_t
217# pragma GCC poison BOOL
218#if !defined(MYSQL_TOKUDB_ENGINE)
219# pragma GCC poison FALSE
220# pragma GCC poison TRUE
221#endif // MYSQL_TOKUDB_ENGINE
222#endif
223#pragma GCC poison __sync_fetch_and_add
224#pragma GCC poison __sync_fetch_and_sub
225#pragma GCC poison __sync_fetch_and_or
226#pragma GCC poison __sync_fetch_and_and
227#pragma GCC poison __sync_fetch_and_xor
228#pragma GCC poison __sync_fetch_and_nand
229#pragma GCC poison __sync_add_and_fetch
230#pragma GCC poison __sync_sub_and_fetch
231#pragma GCC poison __sync_or_and_fetch
232#pragma GCC poison __sync_and_and_fetch
233#pragma GCC poison __sync_xor_and_fetch
234#pragma GCC poison __sync_nand_and_fetch
235#pragma GCC poison __sync_bool_compare_and_swap
236#pragma GCC poison __sync_val_compare_and_swap
237#pragma GCC poison __sync_synchronize
238#pragma GCC poison __sync_lock_test_and_set
239#pragma GCC poison __sync_release
240#endif
241
242#if defined(__cplusplus)
243};
244#endif
245
246void *os_malloc(size_t) __attribute__((__visibility__("default")));
247// Effect: See man malloc(2)
248
249void *os_malloc_aligned(size_t /*alignment*/, size_t /*size*/) __attribute__((__visibility__("default")));
250// Effect: Perform a malloc(size) with the additional property that the returned pointer is a multiple of ALIGNMENT.
251// Requires: alignment is a power of two.
252
253
254void *os_realloc(void*,size_t) __attribute__((__visibility__("default")));
255// Effect: See man realloc(2)
256
257void *os_realloc_aligned(size_t/*alignment*/, void*,size_t) __attribute__((__visibility__("default")));
258// Effect: Perform a realloc(p, size) with the additional property that the returned pointer is a multiple of ALIGNMENT.
259// Requires: alignment is a power of two.
260
261void os_free(void*) __attribute__((__visibility__("default")));
262// Effect: See man free(2)
263
264size_t os_malloc_usable_size(const void *p) __attribute__((__visibility__("default")));
265// Effect: Return an estimate of the usable size inside a pointer. If this function is not defined the memory.cc will
266// look for the jemalloc, libc, or darwin versions of the function for computing memory footprint.
267
268// full_pwrite and full_write performs a pwrite, and checks errors. It doesn't return unless all the data was written. */
269void toku_os_full_pwrite (int fd, const void *buf, size_t len, toku_off_t off) __attribute__((__visibility__("default")));
270void toku_os_full_write (int fd, const void *buf, size_t len) __attribute__((__visibility__("default")));
271
272// os_write returns 0 on success, otherwise an errno.
273ssize_t toku_os_pwrite (int fd, const void *buf, size_t len, toku_off_t off) __attribute__((__visibility__("default")));
274int toku_os_write(int fd, const void *buf, size_t len)
275 __attribute__((__visibility__("default")));
276
277// wrappers around file system calls
278void toku_os_recursive_delete(const char *path);
279
280TOKU_FILE *toku_os_fdopen_with_source_location(int fildes,
281 const char *mode,
282 const char *filename,
283 const toku_instr_key &instr_key,
284 const char *src_file,
285 uint src_line);
286#define toku_os_fdopen(FD, M, FN, K) \
287 toku_os_fdopen_with_source_location(FD, M, FN, K, __FILE__, __LINE__)
288
289TOKU_FILE *toku_os_fopen_with_source_location(const char *filename,
290 const char *mode,
291 const toku_instr_key &instr_key,
292 const char *src_file,
293 uint src_line);
294#define toku_os_fopen(F, M, K) \
295 toku_os_fopen_with_source_location(F, M, K, __FILE__, __LINE__)
296
297int toku_os_open_with_source_location(const char *path,
298 int oflag,
299 int mode,
300 const toku_instr_key &instr_key,
301 const char *src_file,
302 uint src_line);
303#define toku_os_open(FD, F, M, K) \
304 toku_os_open_with_source_location(FD, F, M, K, __FILE__, __LINE__)
305
306int toku_os_open_direct(const char *path,
307 int oflag,
308 int mode,
309 const toku_instr_key &instr_key);
310
311int toku_os_delete_with_source_location(const char *name,
312 const char *src_file,
313 uint src_line);
314#define toku_os_delete(FN) \
315 toku_os_delete_with_source_location(FN, __FILE__, __LINE__)
316
317int toku_os_rename_with_source_location(const char *old_name,
318 const char *new_name,
319 const char *src_file,
320 uint src_line);
321#define toku_os_rename(old_name, new_name) \
322 toku_os_rename_with_source_location(old_name, new_name, __FILE__, __LINE__)
323
324void toku_os_full_write_with_source_location(int fd,
325 const void *buf,
326 size_t len,
327 const char *src_file,
328 uint src_line);
329#define toku_os_full_write(FD, B, L) \
330 toku_os_full_write_with_source_location(FD, B, L, __FILE__, __LINE__)
331
332int toku_os_write_with_source_location(int fd,
333 const void *buf,
334 size_t len,
335 const char *src_file,
336 uint src_line);
337#define toku_os_write(FD, B, L) \
338 toku_os_write_with_source_location(FD, B, L, __FILE__, __LINE__)
339
340void toku_os_full_pwrite_with_source_location(int fd,
341 const void *buf,
342 size_t len,
343 toku_off_t off,
344 const char *src_file,
345 uint src_line);
346#define toku_os_full_pwrite(FD, B, L, O) \
347 toku_os_full_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__)
348
349ssize_t toku_os_pwrite_with_source_location(int fd,
350 const void *buf,
351 size_t len,
352 toku_off_t off,
353 const char *src_file,
354 uint src_line);
355
356#define toku_os_pwrite(FD, B, L, O) \
357 toku_os_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__)
358
359int toku_os_fwrite_with_source_location(const void *ptr,
360 size_t size,
361 size_t nmemb,
362 TOKU_FILE *stream,
363 const char *src_file,
364 uint src_line);
365
366#define toku_os_fwrite(P, S, N, FS) \
367 toku_os_fwrite_with_source_location(P, S, N, FS, __FILE__, __LINE__)
368
369int toku_os_fread_with_source_location(void *ptr,
370 size_t size,
371 size_t nmemb,
372 TOKU_FILE *stream,
373 const char *src_file,
374 uint src_line);
375#define toku_os_fread(P, S, N, FS) \
376 toku_os_fread_with_source_location(P, S, N, FS, __FILE__, __LINE__)
377
378TOKU_FILE *toku_os_fopen_with_source_location(const char *filename,
379 const char *mode,
380 const toku_instr_key &instr_key,
381 const char *src_file,
382 uint src_line);
383
384int toku_os_fclose_with_source_location(TOKU_FILE *stream,
385 const char *src_file,
386 uint src_line);
387
388#define toku_os_fclose(FS) \
389 toku_os_fclose_with_source_location(FS, __FILE__, __LINE__)
390
391int toku_os_close_with_source_location(int fd,
392 const char *src_file,
393 uint src_line);
394#define toku_os_close(FD) \
395 toku_os_close_with_source_location(FD, __FILE__, __LINE__)
396
397ssize_t toku_os_read_with_source_location(int fd,
398 void *buf,
399 size_t count,
400 const char *src_file,
401 uint src_line);
402
403#define toku_os_read(FD, B, C) \
404 toku_os_read_with_source_location(FD, B, C, __FILE__, __LINE__);
405
406ssize_t inline_toku_os_pread_with_source_location(int fd,
407 void *buf,
408 size_t count,
409 off_t offset,
410 const char *src_file,
411 uint src_line);
412#define toku_os_pread(FD, B, C, O) \
413 inline_toku_os_pread_with_source_location(FD, B, C, O, __FILE__, __LINE__);
414
415void file_fsync_internal_with_source_location(int fd,
416 const char *src_file,
417 uint src_line);
418
419#define file_fsync_internal(FD) \
420 file_fsync_internal_with_source_location(FD, __FILE__, __LINE__);
421
422int toku_os_get_file_size_with_source_location(int fildes,
423 int64_t *fsize,
424 const char *src_file,
425 uint src_line);
426
427#define toku_os_get_file_size(D, S) \
428 toku_os_get_file_size_with_source_location(D, S, __FILE__, __LINE__)
429
430// TODO: should this prototype be moved to toku_os.h?
431int toku_stat_with_source_location(const char *name,
432 toku_struct_stat *buf,
433 const toku_instr_key &instr_key,
434 const char *src_file,
435 uint src_line)
436 __attribute__((__visibility__("default")));
437
438#define toku_stat(N, B, K) \
439 toku_stat_with_source_location(N, B, K, __FILE__, __LINE__)
440
441int toku_os_fstat_with_source_location(int fd,
442 toku_struct_stat *buf,
443 const char *src_file,
444 uint src_line)
445 __attribute__((__visibility__("default")));
446
447#define toku_os_fstat(FD, B) \
448 toku_os_fstat_with_source_location(FD, B, __FILE__, __LINE__)
449
450#ifdef HAVE_PSI_FILE_INTERFACE2
451int inline_toku_os_close(int fd, const char *src_file, uint src_line);
452int inline_toku_os_fclose(TOKU_FILE *stream,
453 const char *src_file,
454 uint src_line);
455ssize_t inline_toku_os_read(int fd,
456 void *buf,
457 size_t count,
458 const char *src_file,
459 uint src_line);
460ssize_t inline_toku_os_pread(int fd,
461 void *buf,
462 size_t count,
463 off_t offset,
464 const char *src_file,
465 uint src_line);
466int inline_toku_os_fwrite(const void *ptr,
467 size_t size,
468 size_t nmemb,
469 TOKU_FILE *stream,
470 const char *src_file,
471 uint src_line);
472int inline_toku_os_fread(void *ptr,
473 size_t size,
474 size_t nmemb,
475 TOKU_FILE *stream,
476 const char *src_file,
477 uint src_line);
478int inline_toku_os_write(int fd,
479 const void *buf,
480 size_t len,
481 const char *src_file,
482 uint src_line);
483ssize_t inline_toku_os_pwrite(int fd,
484 const void *buf,
485 size_t len,
486 toku_off_t off,
487 const char *src_file,
488 uint src_line);
489void inline_toku_os_full_write(int fd,
490 const void *buf,
491 size_t len,
492 const char *src_file,
493 uint src_line);
494void inline_toku_os_full_pwrite(int fd,
495 const void *buf,
496 size_t len,
497 toku_off_t off,
498 const char *src_file,
499 uint src_line);
500int inline_toku_os_delete(const char *name,
501 const char *srv_file,
502 uint src_line);
503//#else
504int inline_toku_os_close(int fd);
505int inline_toku_os_fclose(TOKU_FILE *stream);
506ssize_t inline_toku_os_read(int fd, void *buf, size_t count);
507ssize_t inline_toku_os_pread(int fd, void *buf, size_t count, off_t offset);
508int inline_toku_os_fwrite(const void *ptr,
509 size_t size,
510 size_t nmemb,
511 TOKU_FILE *stream);
512int inline_toku_os_fread(void *ptr,
513 size_t size,
514 size_t nmemb,
515 TOKU_FILE *stream);
516int inline_toku_os_write(int fd, const void *buf, size_t len);
517ssize_t inline_toku_os_pwrite(int fd,
518 const void *buf,
519 size_t len,
520 toku_off_t off);
521void inline_toku_os_full_write(int fd, const void *buf, size_t len);
522void inline_toku_os_full_pwrite(int fd,
523 const void *buf,
524 size_t len,
525 toku_off_t off);
526int inline_toku_os_delete(const char *name);
527#endif
528
529// wrapper around fsync
530void toku_file_fsync(int fd);
531int toku_fsync_directory(const char *fname);
532void toku_file_fsync_without_accounting(int fd);
533
534// get the number of fsync calls and the fsync times (total)
535void toku_get_fsync_times(uint64_t *fsync_count,
536 uint64_t *fsync_time,
537 uint64_t *long_fsync_threshold,
538 uint64_t *long_fsync_count,
539 uint64_t *long_fsync_time);
540
541void toku_set_func_fsync (int (*fsync_function)(int));
542void toku_set_func_pwrite (ssize_t (*)(int, const void *, size_t, toku_off_t));
543void toku_set_func_full_pwrite (ssize_t (*)(int, const void *, size_t, toku_off_t));
544void toku_set_func_write (ssize_t (*)(int, const void *, size_t));
545void toku_set_func_full_write (ssize_t (*)(int, const void *, size_t));
546void toku_set_func_fdopen (FILE * (*)(int, const char *));
547void toku_set_func_fopen (FILE * (*)(const char *, const char *));
548void toku_set_func_open (int (*)(const char *, int, int));
549void toku_set_func_fclose(int (*)(FILE *));
550void toku_set_func_read(ssize_t (*)(int, void *, size_t));
551void toku_set_func_pread(ssize_t (*)(int, void *, size_t, off_t));
552void toku_set_func_fwrite(
553 size_t (*fwrite_fun)(const void *, size_t, size_t, FILE *));
554
555int toku_portability_init(void);
556void toku_portability_destroy(void);
557
558// Effect: Return X, where X the smallest multiple of ALIGNMENT such that X>=V.
559// Requires: ALIGNMENT is a power of two
560static inline uint64_t roundup_to_multiple(uint64_t alignment, uint64_t v) {
561 return (v + alignment - 1) & ~(alignment - 1);
562}
563