dot.bashrc の設定

dot.bashrc の設定。

alias ls='ls --show-control-char'
alias ll='ls -l'
alias lld='ls -ld'
alias lla='ls -la'

#alias e='emacs-w32.exe -r'
#alias e='emacs'
alias e='/app/cygwin/emacs/bin/emacs'

export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

# man の出力を均等割り付けしない
export MANOPT=--no-justification

# gnupack の /app/cygwin/local/bin を PATH に追加しておく
# (/etc/fstab を編集し C:/gnupack/gnupack_devel-13.06-2015.11.08/app を /app にマウントしている)
# /usr/local にマウントしたので PATH いらない。
#export PATH=/app/cygwin/local/bin:$PATH

# 自分用のPATH
export PATH=~/bin:$PATH


# dircolors の設定 (dircolors の出力をセット)
LS_COLORS='rs=0:di=01;34:ln=01;36:...:*.xspf=00;36:';
export LS_COLORS

dot.emacs の設定

新しいの

;;--------------------------------------------------
;; Load Path
;;--------------------------------------------------

;; Added by Package.el.  This must come before configurations of
;; installed packages.  Don't delete this line.  If you don't want it,
;; just comment it out by adding a semicolon to the start of the line.
;; You may delete these explanatory comments.
(package-initialize)

(setq load-path
      (append
       (list (expand-file-name "~/mylisp"))
       load-path))

;;--------------------------------------------------
;; theme
;;--------------------------------------------------
(load-theme 'zenburn t)
;;(load-theme 'hc-zenburn t)

;;--------------------------------------------------
;; Package
;;--------------------------------------------------
(require 'package)
;; melpa を追加
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

(package-initialize)

;;--------------------------------------------------
;; Language Settings
;;--------------------------------------------------
;; set language as Japanese
(set-language-environment 'Japanese)
;; coding UTF8
(set-language-environment  'utf-8)
(prefer-coding-system 'utf-8)


;;--------------------------------------------------
;; Key bindings
;;--------------------------------------------------
;; C-z
(global-set-key "\C-z" 'undo)
;; C-x C-z
(global-set-key "\C-x\C-z" 'suspend-emacs)
;; C-h
;;(global-set-key "\C-h" 'delete-backward-char)
;; help
;;(global-set-key "\C-c\C-h" 'help-command)
;; comment out
;;(global-set-key "\C-c;" 'comment-dwim)
;; move window
;;(global-set-key "\C-t" 'other-window)
(global-set-key [f9] 'other-window)
;; move buffer
(global-set-key [f11] 'previous-buffer)
(global-set-key [f12] 'next-buffer)

;; next-error (default)
;;(global-set-key "\M-gn" 'next-error)
;; prev-error (default)
;;(global-set-key "\M-gp" 'prev-error)

;; open header or #include file.
(global-set-key "\C-c\C-h" 'ff-find-other-file)


;;--------------------------------------------------
;; Mouse
;;--------------------------------------------------
(xterm-mouse-mode t)



;;--------------------------------------------------
;; Preference
;;--------------------------------------------------
;; デフォルトの起動時のメッセージを表示しない
(setq inhibit-startup-message t)

;; メニューバーの非表示
(menu-bar-mode -1)

;; ツールバーの非表示
(tool-bar-mode -1)

;; 分割数を制限
(setq split-height-threshold nil)
(setq split-width-thireshold nil)

;; Disk上のファイルが変更されたらそれを読み込む。
;;(setq global-auto-revert-mode 1)

;; font-lock mode いるかね? 遅くならない?
;;(global-font-lock-mode t)

;; ファイルの末尾は改行になるのを強制
;;(setq require-final-newline t)

;; next-line でバッファの最後に改行を入れない(今はデフォルトで nil なので設定不要)
;;(setq next-line-add-newlines nil)

;; Emacsの終了が遅くなるので Backup は作らない
(setq backup-inhibited t)
(setq delete-auto-save-files t)
(setq make-backup-files nil)
(setq auto-save-default nil)

;; でも編集位置は記憶しておく。終了が遅くなるけど
(save-place-mode 1)

;; 列の番号を表示
(column-number-mode t)

;; 行番号を表示
(global-linum-mode t)
(setq linum-format "%5d ")
;;(set-face-attribute 'linum nil :foreground "gray55" :background "gray20")

;; 関数名を表示
(which-function-mode t)

;;(setq-default scroll-step 0)
;; 右端で折り返さない
;;(setq-default truncate-lines t)
;; C-x 3 などの縦分割ウィンドウで右端で折り返さない
;;(setq-default truncate-partial-width-windows t)

;; コンパイル時のウィンドウの高さ
(setq-default compilation-window-height 10)




;; Tabにスペース4つを利用
(setq-default tab-width 4)
(setq-default indent-tabs-mode nil)

;; 1行ごとにスクロールする (1 だとたまにジャンプするので巨大数を指定する)
(setq scroll-conservatively 10000)

;; スクロール時にカーソル位置を保持
(setq scroll-preserve-screen-position t)

;; スクロールの上下マージン
(setq-default scroll-margin 1)

;; カーソル行を一瞬光らせる
(beacon-mode 1)

;; カーソル行をハイライト
;; customize-face で常に hl-face がデフォルトになったりするので使わない
;; (GLOBAL-hl-line-mode nil)

;; BS や Delete キーでリージョン内の文字を削除
(delete-selection-mode 1)

;; selection hilighting (デフォルトで t なので設定不要)
;;(setq-default transient-mark-mode t)

;; 対応する括弧を光らせる
(show-paren-mode t)

;; 括弧を自動で補完する
(electric-pair-mode 1)

;; 行頭の C-k で改行も kill する
(setq kill-whole-line t)

;; 最近開いたファイルが File メニュー内にあらわさる
;; ivy 使うのでいらない
;;(recentf-mode)


;;--------------------------------------------------
;; C-Mode Common Hook
;;--------------------------------------------------
(defun my-c-mode-common-hook ()
  ;; ggtags on
  (ggtags-mode t)

  ;; 行コメント開始位置
  (setq   comment-column 48)

  ;; コメント形式
  ;; (setq comment-start "/* ")
  ;; (setq comment-end " */")
  ;; (setq comment-style (quote aligned))

  ;; case sensitive search
  ;;(setq case-fold-search nil)

  ;; Backcpaceでタブを空白に変換しない
  ;; (setq c-backspace-function 'backward-delete-char)

  ;; hungry-delete
  ;;(setq c-hungry-delete-key t)

  ;; インデント情報の表示
  ;; (setq c-echo-syntactic-information-p t)

  ;; ワード単位の移動 camelCase に対応
  ;; (subword-mode)

  ;; styleの選択。いらないのでは? これが重くなく原因かな。
  ;;(c-set-style "stroustrup")

  ;; インデント規則 (c-set-style の後に設定する必要がある)
  (c-set-offset 'innamespace 0)
  (c-set-offset 'defun-block-intro +4)
  (c-set-offset 'statement-block-intro +4)
  )
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

;;--------------------------------------------------
;; ivy/counsel
;;--------------------------------------------------
(ivy-mode 1)

(setq enable-recursive-minibuffers t)
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d)")

;; 候補の表示行数最大値
(setq ivy-height (truncate (* (window-height) 0.5)))
;;(setq ivy-height 32)

;; 常に固定の行数を表示するかどうか
;;(setq ivy-fixed-height-minibuffer nil)

;; Keybindings
;;(global-set-key (kbd "M-x") 'counsel-M-x)
;;(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "C-c c s") 'swiper)
(global-set-key (kbd "C-C C-r") 'ivy-resume)


;;--------------------------------------------------
;; counsel-gtags
;;--------------------------------------------------
(add-hook 'c-mode-hook 'counsel-gtags-mode)
(add-hook 'c++-mode-hook 'counsel-gtags-mode)

(with-eval-after-load 'counsel-gtags
  (define-key counsel-gtags-mode-map (kbd "C-c g b") 'counsel-gtags-go-backward)
  (define-key counsel-gtags-mode-map (kbd "C-c g f") 'counsel-gtags-go-forward)
  (define-key counsel-gtags-mode-map (kbd "C-]") 'counsel-gtags-dwim)
  (define-key counsel-gtags-mode-map (kbd "C-t") 'counsel-gtags-go-backward)
  )


;;--------------------------------------------------
;; 
;;--------------------------------------------------
(which-key-mode t)


;;--------------------------------------------------
;; Customize Settings
;;--------------------------------------------------
;; カスタマイズを保存するファイル
(setq custom-file "~/.emacs.d/customize_settings.el")
;; カスタマイズ用ファイルをロード
(load custom-file t)

古いの

dot.emacs

追加で使っているelispcygwin-mount.el, doxymacs.el と gtags.el くらい。

(global-set-key [delete] 'delete-char)
(global-set-key [kp-delete] 'delete-char)

;; open #include <...> file
(global-set-key "\C-c\C-h" 'ff-find-other-file)

;;(global-set-key [home] 'beginning-of-line)
;;(global-set-key [end] 'end-of-line)
;;(global-set-key [C-home] 'beginning-of-buffer)
;;(global-set-key [C-end] 'end-of-buffer)
;;(global-set-key [C-tab] 'bs-cycle-previous)
;;(global-set-key [C-S-iso-lefttab] 'bs-cycle-next)

;; C-z では、suspend-emacs関数が呼ばれるが、C-x C-zでも同じ
;; なので、C-zはUndoにする
(global-set-key "\C-z" 'advertised-undo)               ;; C-x u (Undo)

;;(global-set-key [find] 'overwrite-mode)                ;; PC Insert key
;;(global-set-key [insertchar] 'beginning-of-line)       ;; PC Home key
;;(global-set-key [prior] 'end-of-line)                  ;; PC End key
;;(global-set-key [deletechar] 'scroll-down)             ;; PC PageUp key
(global-set-key [find] 'beginning-of-line)             ;; PC Home key
(global-set-key [select] 'end-of-line)                 ;; PC End key
(global-set-key [insertchar] 'overwrite-mode)          ;; PC Insert key

;;(global-set-key [f3] 'delete-other-windows)

;; ビルド&エラー検索用 ビルド&エラー検索キーマップキーマップ
(global-set-key [f4] 'next-error)
(global-set-key [f14] 'previous-error) ;; f14 == Shift F4
(global-set-key [f5] 'compilation-mode)

;; カレントワードのmanを起動
(global-set-key  [f6]  (lambda () (interactive) (manual-entry (current-word))))
;;(setq manual-program "jmanx")

(global-set-key [f7] 'compile)
(global-set-key [f8] 'grep)

;; same as C-x o
(global-set-key [f9] 'other-window)

;; move buffer
(global-set-key [f11] 'bs-cycle-previous)
(global-set-key [f12] 'bs-cycle-next)


(global-set-key [mouse-4] 'scroll-down)
(global-set-key [mouse-5] 'scroll-up)


;; (cd "~/")

;; font-lock mode
(global-font-lock-mode t)

;; visual feedback on selections
(setq-default transient-mark-mode t)

;; last newline
(setq require-final-newline t)

;; not add lines
(setq next-line-add-newlines nil)

;;(setq backup-inhibited t)
;;(setq delete-auto-save-files t)
;;(setq make-backup-files nil)
;;(setq auto-save-default nil)

;; 列数を表示する
(column-number-mode t)

;; 左端に行数を表示する
(global-linum-mode t)

 ;; カーソルの点滅をやめる
(blink-cursor-mode 0)

;; カーソル行をハイライトする
;;(global-hl-line-mode t)

(setq kill-whole-line t)

(display-time)

(which-function-mode 1)

(recentf-mode)

;; 対応する括弧を光らせる
(show-paren-mode t)
;;(setq show-paren-style 'mixed)        ;; 対応する括弧が画面外のときだけ内容を色変え
;;(setq show-paren-style 'expression)     ;; 常に色変え
(set-face-background 'show-paren-match-face "blue") ;; "gray10")
(set-face-foreground 'show-paren-match-face "skyblue")  ;;"SkyBlue")

;; スペース、タブなどを可視化
;; コンソールだと化ける→;; (global-whitespace-mode 1)

;; スクロールは1行ごとに
(setq scroll-conservatively 10000)

;; シフト+矢印で範囲選択
;;(setq pc-select-selection-keys-only t)
;;(pc-selection-mode 1)

(setq default-tab-width 4)
;;(add-hook 'shell-mode-hook '(lamda () (setq tab-width 8))) ;; shellモードはタブ8でないと化けるらしい
(setq auto-mode-alist (cons '("\\.h\\'" . c++-mode) auto-mode-alist))

::(setq vc-default-back-end 'CVS)

;; (setq compile-command "date; gcc -g -Wall -o ")

(setq-default scroll-step 0)

;; 右端で折り返さない
;;(setq-default truncate-lines t)

;; C-x 3 などの縦分割ウィンドウで右端で折り返さない
;;(setq-default truncate-partial-width-windows t)

(setq-default compilation-window-height 10)

;;(setq frame-title-format (format "emacs@%s : %%f" (system-name)))
(setq-default frame-title-format "%b")

;; スクロール時にカーソル位置を保持
(setq scroll-preserve-screen-position t)

;; BS や Delete キーでリージョン内の文字を削除
(delete-selection-mode 1)

;; find file at point #include <stdio.h>とか開いてくれる
;; 従来のFindFindはC-u C-x C-Fとなる。
(ffap-bindings)
(setq ffap-c-path
      '("/usr/include"
        "/usr/include/c++/3.2"
        "/usr/local/include"
        "../include"))


(defun my-c-mode-common-hook ()
    ;; my customizations for all of c-mode and related modes

    ;; コンパイルのときに毎回訊きに来ない
    ;;(setq compilation-read-command nil)

    ;; compileのときに使うコマンド
    ;;(set (make-local-variable 'compile-command) "make -k -C ../Build")

    ;; 
    (setq   comment-column 48)

    ;; 先頭でのTabのみインデント処理する。Tab <==> M-i の入れ替えをするので不要
    ;; (setq c-tab-always-indent nil)

    ;; { の入力などで自動インデント処理
    ;; (setq c-auto-newline t)

    ;; 基本インデント量
    (setq c-basic-offset 4)

    ;; Tabは4
    (setq tab-width 4)

    ;; タブストップの位置
    (setq tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156))

    ;; case sensitive
    ;;(setq case-fold-search nil)
    (setq case-fold-search t)

    ;; 後退の時タブをスペースに変換しない
    (setq c-backspace-function 'backward-delete-char)

    ;; インデント情報の表示
    (setq c-echo-syntactic-information-p t)

    ;; EnterとC-jの交換
    (local-set-key "\C-m" 'newline-and-indent)      ;; ReturnをC-jにする
    (local-set-key "\C-j" 'newline)                 ;; C-j をReturnにする

    ;; TabとM-iの交換
;   (local-set-key "\C-i" 'tab-to-tab-stop)         ;; Tabキーを普通のTabに
;   (local-set-key "\M-i" 'c-indent-command)        ;; M-iキーをインデントにする

    ;; if/for/whileなどの次の行はインデントはそのまま。
    (c-set-offset 'substatement-open    0)
    ;;(c-set-offset 'comment-intro      0)

    ;; 右端で折り返さない
    (setq truncate-lines t)                 ;; 右端で折り返さない cmd:toggle-truncate-lines
    (setq truncate-partial-width-windows t) ;; C-x 3など縦分割ウィンドウで右端で折り返さない

    ;; ワード単位の移動で camelCase に対応
;   (subword-mode)
    )

(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)



;;~/bak/にバックアップ作成
(setq backup-by-copying t)
(fset 'make-backup-file-name
      '(lambda (file)
          (concat (expand-file-name "~/bak/")
                  (file-name-nondirectory file))
         ))
(if (file-exists-p "~/bak/")
    (setq auto-save-list-file-prefix "~/bak/"))

(setq make-backup-files t)
(setq backup-directory-alist
      (cons (cons "\\.*$" (expand-file-name "~/bak"))
            backup-directory-alist))

;; かんたんなVersionControl
(setq version-control t)

;; 新しいものをいくつ残すか
(setq kept-new-versions 2)

;; 古いものをいくつ残すか
(setq kept-old-versions 2)

;; 尋ねずに削除
(setq delete-old-versions t)

;; 編集位置を記憶
(load "saveplace")
(setq-default save-place t)


;;ロードパスを追加
(setq load-path
      (append
       (list (expand-file-name "~/mylisp")) load-path))

;; 罫線lispの設定
(if window-system
    (autoload 'keisen-mode "keisen-mouse" "MULE 版罫線モード + マウス" t)
  (autoload 'keisen-mode "keisen-mule" "MULE 版罫線モード" t))



(require 'doxymacs)
(add-hook 'c-mode-common-hook 'doxymacs-mode)


(require 'gtags)

;; If you hope gtags-mode is on in c-mode then please add c-mode-hook to your
;; $HOME/.emacs like this.
;;
(setq c-mode-hook
    '(lambda ()
    (gtags-mode 1)
))

;; There are two hooks, gtags-mode-hook and gtags-select-mode-hook.
;; The usage of the hook is shown as follows.
;;
;; [Setting to reproduce old 'Gtags mode']
;;
;; (setq gtags-mode-hook
;;   '(lambda ()
;;      (setq gtags-pop-delete t)
;;      (setq gtags-path-style 'absolute)
;; ))
;;
;; [Setting to make 'Gtags select mode' easy to see]
;;
(setq gtags-select-mode-hook
  '(lambda ()
     (setq hl-line-face 'underline)
     (hl-line-mode 1)
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GNU GLOBAL(gtags)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
      '(lambda ()
         (local-set-key "\M-t" 'gtags-find-tag)
         (local-set-key "\M-r" 'gtags-find-rtag)
         (local-set-key "\M-s" 'gtags-find-symbol)
         ;(local-set-key "\C-t" 'gtags-pop-stack)
         ))

(setq inhibit-startup-message t)        ; 開始メッセージを削除
(menu-bar-mode -1)                      ; メニューを消す
(tool-bar-mode -1)                      ; ツールバーを消す

;; region の色
(set-face-background 'region "SkyBlue")
(set-face-foreground 'region "black")

(if (boundp 'window-system)
    (setq initial-frame-alist
          (append (list
                   '(foreground-color . "azure3") ;; 文字が白
                   '(background-color . "black") ;; 背景は黒
                   '(border-color     . "black")
                   '(mouse-color      . "white")
                   '(cursor-color     . "white")
                   '(cursor-type      . box)
                   '(menu-bar-lines . 1)
                   ;'(vertical-scroll-bars . nil) ;;スクロールバーはいらない
                   ;;'(font . "MS Gothic 12")
                   '(font . "MS Gothic 9")
                   '(width . 120) ;; ウィンドウ幅
                   '(height . 50) ;; ウィンドウの高さ
                   '(top . 0) ;;表示位置
                   ;;'(left . 50) ;;表示位置
                   '(left . 0) ;;表示位置
                   )
                  initial-frame-alist)))
(setq default-frame-alist initial-frame-alist)

;;(require 'cygwin-mount)                   ; cygwin-mount
;;(cygwin-mount-activate)                   ; cygwin-mount


;; rubydb - ruby debugger
;;(autoload 'rubydb "rubydb3x" "ruby debug" t)




(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(comment-style (quote extra-line))
 '(ediff-make-buffers-readonly-at-startup t)
 '(ediff-split-window-function (quote split-window-horizontally))
 '(line-move-visual t))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

StoreBuffer(仮)

StoreBuffer とりあえずコンパイル通った版。

#include <stdio.h>
#include <string.h>
#include "type.h"
#include "util.h"
#include "Dmac.h"
#include "StoreBuffer.h"




#define MAX_STORE_BUFFER_NUM    4
#define MAX_LINE_NUM            32
#define MIN_LINE_SIZE           16




typedef struct STORE_BUFFER_T {
    UINT32                      buffer;         /* store buffer */
    UINT32                      capacity;       /* size of buffer in bytes */
    UINT32                      lineSize;       /* size of cache line in bytes */
    UINT32                      lineNum;        /* count of cache line */
    UINT32                      lineUsed;       /* count of used cache line */
    UINT32                      lineDict[MAX_LINE_NUM]; /* high bit: destination address.
                                                           low  bit: index of cache line.
                                                           The number of bits changes according to
                                                           the lineSize.
                                                           */
    UINT32                      destBeg;        /* begin address of destination */
    UINT32                      destEnd;        /* end address of destination (exclude this) */
    UINT8                       flag;           /* flag */
} STORE_BUFFER_T;

/* STORE_BUFFER_T.flag */
#define FLAG_USED               0x01
#define FLAG_PRELOAD            0x02



typedef struct STORE_BUFFER_WORK_T {
    STORE_BUFFER_T              storeBuffer[MAX_STORE_BUFFER_NUM];
} STORE_BUFFER_WORK_T;




PRIVATE STORE_BUFFER_WORK_T     sMtkStoreBufferWork;



#define work                    (&sMtkStoreBufferWork)
#define getItem(id)             (&work->storeBuffer[id])
#define checkID(id)             ((0 <= id) && (id < MAX_STORE_BUFFER_NUM))



PRIVATE UINT32 MostLeftHighBit(UINT32 data);
PRIVATE void* GetLine(STORE_BUFFER_T* self, void* dest);
PRIVATE UINT32 GetDict(STORE_BUFFER_T* self, void* dest);
PRIVATE UINT32* SearchDict(STORE_BUFFER_T* self, void* dest);
PRIVATE UINT32* AllocDict(STORE_BUFFER_T* self, void* dest);
PRIVATE void Preload(STORE_BUFFER_T* self, UINT32 dict);
PRIVATE void RotateMruDict(STORE_BUFFER_T* self, UINT32 index);
PRIVATE void FlushLruDict(STORE_BUFFER_T* self);
PRIVATE BOOL CheckDestRange(STORE_BUFFER_T* self, void* dest);
PRIVATE UINT32 WriteLine(STORE_BUFFER_T* self, void* line, const void* dest, const void* src, UINT32 size);
PRIVATE UINT32 FillLine(STORE_BUFFER_T* self, void* line, const void* dest, INT filler, UINT32 size);
PRIVATE void ShellSort(UINT32* arr, UINT32 num);
PRIVATE void JoinWrite(STORE_BUFFER_T* self);




void MtkInitializeStoreBuffer(void)
{
    memset(work, 0, sizeof(*work));
}

INT MtkCreateStoreBuffer(void* buffer, UINT32 capacity, UINT32 lineSize, void* destBeg, void* destEnd)
{
    INT id;
    STORE_BUFFER_T* sb;
    INT i;

    for (id = 0; id < MAX_STORE_BUFFER_NUM; ++id) {
        sb = getItem(id);
        if (MTK_BTST(sb->flag, FLAG_USED) == 0) {
            break;
        }
    }
    if (id >= MAX_STORE_BUFFER_NUM) {
        return INVALID_STORE_BUFFER_ID;
    }

    lineSize = MostLeftHighBit(lineSize);
    lineSize = MTK_MIN(lineSize, capacity);
    lineSize = MTK_MAX(lineSize, MIN_LINE_SIZE);

    sb->buffer   = (UINT32) buffer;
    sb->capacity = capacity;
    sb->lineSize = lineSize;
    sb->lineNum  = capacity / lineSize;
    sb->lineNum  = MTK_MIN(sb->lineNum, MAX_LINE_NUM);
    sb->lineUsed = 0;
    for (i = 0; i < MAX_LINE_NUM; ++i) {
        sb->lineDict[i] = i;                    /* set cache line id into low bits */
    }
    sb->destBeg  = (UINT32) destBeg;
    sb->destEnd  = (UINT32) destEnd;
    sb->flag     = FLAG_USED;

    return id;
}

void MtkDestroyStoreBuffer(INT id)
{
    STORE_BUFFER_T* sb;

    if (! checkID(id)) {
        return;
    }

    MtkFlushStoreBuffer(id);

    sb = getItem(id);

    MTK_BCLR(sb->flag, FLAG_USED);
}

BOOL MtkSetPreload(INT id,  BOOL preload)
{
    STORE_BUFFER_T* sb;

    if (! checkID(id)) {
        return FALSE;
    }

    sb = getItem(id);

    if (preload) {
        MTK_BSET(sb->flag, FLAG_PRELOAD);
    }
    else {
        MTK_BCLR(sb->flag, FLAG_PRELOAD);
    }

    return TRUE;
}

BOOL MtkWriteStoreBuffer(INT id, void* dest, const void* src, UINT32 size)
{
    STORE_BUFFER_T* sb;
    void* line;
    UINT32 written;

    if (! checkID(id)) {
        return FALSE;
    }

    sb = getItem(id);

    if (! CheckDestRange(sb, dest)) {
        return FALSE;
    }

    do {
        line    = GetLine(sb, dest);
        written = WriteLine(sb, line, dest, src, size);
        dest    = (      void*)((UINT32)dest + written);
        src     = (const void*)((UINT32)src  + written);
        size   -= written;
    } while (size);

    return TRUE;
}

BOOL MtkFillStoreBuffer(INT id, void* dest, INT filler, UINT32 size)
{
    STORE_BUFFER_T* sb;
    void* line;
    UINT32 written;

    if (! checkID(id)) {
        return FALSE;
    }

    sb = getItem(id);

    if (! CheckDestRange(sb, dest)) {
        return FALSE;
    }

    do {
        line    = GetLine(sb, dest);
        written = FillLine(sb, line, dest, filler, size);
        dest    = (      void*)((UINT32)dest + written);
        size   -= written;
    } while (size);

    return TRUE;
}

BOOL MtkFlushStoreBuffer(INT id)
{
    STORE_BUFFER_T* sb;

    if (! checkID(id)) {
        return FALSE;
    }

    sb = getItem(id);

    /* lineDict[]をソートする */
    ShellSort(sb->lineDict, sb->lineUsed);

    /* destが連続している領域は一気に出力 */
    JoinWrite(sb);

    /* preload を ON にする */
    MTK_BSET(sb->flag, FLAG_PRELOAD);

    return TRUE;
}








PRIVATE UINT32 MostLeftHighBit(UINT32 data)
{
    UINT32 tester = 0x80000000;
    while (tester) {
        if (MTK_BTST(data, tester)) {
            return tester;
        }
        tester >>= 1;
    }
    return 0;
}

PRIVATE void* GetLine(STORE_BUFFER_T* self, void* dest)
{
    UINT32 dict = GetDict(self, dest);
    UINT32 mask = ~(self->lineSize - 1);
    UINT32 index;
    UINT32 line;

    index = MTK_BTST(dict, ~mask);
    line  = self->buffer + self->lineSize * index;

    return (void*)line;
}

PRIVATE UINT32 GetDict(STORE_BUFFER_T* self, void* dest)
{
    UINT32* dict;

    dict = SearchDict(self, dest);
    if (! dict) {
        dict = AllocDict(self, dest);
        if (! dict) {
            FlushLruDict(self);
            dict = AllocDict(self, dest);
        }
    }

    return *dict;
}

PRIVATE UINT32* SearchDict(STORE_BUFFER_T* self, void* dest)
{
    UINT32 mask = ~(self->lineSize - 1);
    INT i;

    /* serch backward for search MRU entry first */
    for (i = self->lineUsed - 1; i >= 0; --i) {
        if (MTK_BTST((UINT32)dest, mask) == MTK_BTST(self->lineDict[i], mask)) {
            RotateMruDict(self, i);
            return &self->lineDict[self->lineUsed - 1];
        }
    }

    return NULL;
}

PRIVATE UINT32* AllocDict(STORE_BUFFER_T* self, void* dest)
{
    UINT32 mask = ~(self->lineSize - 1);
    UINT32 i;

    if (self->lineUsed >= self->lineNum) {
        return NULL;
    }

    i = self->lineUsed++;

    /* @note low bit(cache line id) was saved in lineDict[i]*/
    MTK_BCLR(self->lineDict[i], mask);
    MTK_BSET(self->lineDict[i], MTK_BTST((UINT32)dest, mask));

    if (MTK_BTST(self->flag, FLAG_PRELOAD)) {
        Preload(self, self->lineDict[i]);
    }

    return &self->lineDict[i];
}

PRIVATE void Preload(STORE_BUFFER_T* self, UINT32 dict)
{
    UINT32 mask = ~(self->lineSize - 1);
    UINT32 dest;
    UINT32 index;
    UINT32 line;

    dest  = MTK_BTST(dict, mask);
    index = MTK_BTST(dict, ~mask);
    line  = self->buffer + self->lineSize * index;

    ReadDmac((void*)line, (void*)dest, self->lineSize);
}

PRIVATE void RotateMruDict(STORE_BUFFER_T* self, UINT32 index)
{
    UINT32 tmp = self->lineDict[index];
    UINT32 i;

    for (i = index; i < self->lineNum - 1; ++i) {
        self->lineDict[i] = self->lineDict[i + 1];
    }
    self->lineDict[self->lineNum - 1] = tmp;
}

PRIVATE void FlushLruDict(STORE_BUFFER_T* self)
{
    UINT32 mask = ~(self->lineSize -1);
    UINT32 dict;
    UINT32 dest;
    UINT32 index;
    UINT32 line;
    UINT32 size;

    /*
     * LRU: Least Recently Used
     * lineDict[0] is always LRU dict.
     */
    dict  = self->lineDict[0];
    dest  = MTK_BTST(dict, mask);
    index = MTK_BTST(dict, ~mask);
    line  = self->buffer + self->lineSize * index;
    size  = self->lineSize;

    if (dest < self->destBeg) {
        UINT32 offset = MTK_BTST(self->destBeg, ~mask);
        dest  = self->destBeg;
        size -= offset;
        line += offset;
    }

    if (self->destEnd <= (dest + size)) {
        size = self->destEnd - dest;
    }

    /* printf("FlushLruDict: dest=%08x line=%08x size=%d\n", (INT)dest, (INT)line, (INT)size); */

    WriteDmac((void*)dest, (void*)line, size);

    RotateMruDict(self, 0);
    self->lineUsed--;
    MTK_BSET(self->flag, FLAG_PRELOAD);
}

PRIVATE BOOL CheckDestRange(STORE_BUFFER_T* self, void* dest)
{
    UINT32 mask = ~(self->lineSize - 1);
    UINT32 dest0, beg, end;

    dest0 = MTK_BTST((UINT32)dest, mask);
    beg   = MTK_BTST(self->destBeg, mask);
    end   = MTK_BTST(self->destEnd, mask);

    if ((dest0 < beg) || (end <= dest0)) {
        return FALSE;
    }

    return TRUE;
}

PRIVATE UINT32 WriteLine(STORE_BUFFER_T* self, void* line, const void* dest, const void* src, UINT32 size)
{
    UINT32 mask   = ~(self->lineSize - 1);
    UINT32 offset = MTK_BTST((UINT32)dest, ~mask);
    UINT32 pos    = (UINT32) line + offset;
    UINT32 len    = self->lineSize - offset;
    len = MTK_MIN(len, size);

    memcpy((void*)pos, src, len);

    return len;
}

PRIVATE UINT32 FillLine(STORE_BUFFER_T* self, void* line, const void* dest, INT filler, UINT32 size)
{
    UINT32 mask   = ~(self->lineSize - 1);
    UINT32 offset = MTK_BTST((UINT32)dest, ~mask);
    UINT32 pos    = (UINT32) line + offset;
    UINT32 len    = self->lineSize - offset;
    len = MTK_MIN(len, size);

    memset((void*)pos, filler, len);

    return len;
}

PRIVATE void ShellSort(UINT32* arr, UINT32 num)
{
    UINT32 h;
    UINT32 i, j;

    h = 1;
    while (h < num / 9) {
        h = 3 * h + 1;
    }

    for (; h > 0; h /= 3) {
        for (i = h; i < num; ++i) {
            for (j = i; j >= h; j -= h) {
                if (arr[j - h] > arr[j]) {
                    UINT32 tmp = arr[j - h];
                    arr[j - h] = arr[j];
                    arr[j]     = tmp;
                }
            }
        }
    }
}

PRIVATE void JoinWrite(STORE_BUFFER_T* self)
{
    UINT32 mask = ~(self->lineSize - 1);
    UINT32 dict;
    UINT32 dest;
    UINT32 index;
    UINT32 line;
    UINT32 size;
    UINT32 i;

    LockDmac();

    for (i = 0; i < self->lineUsed; ++i) {
        dict  = self->lineDict[i];
        dest  = MTK_BTST(dict, mask);
        index = MTK_BTST(dict, ~mask);
        line  = self->buffer + self->lineSize * index;
        size  = self->lineSize;

        if (dest < self->destBeg) {
            dest = self->destBeg;
            size = size - (self->destBeg - dest);
            line += MTK_BTST(self->destBeg, ~mask);
        }

        if (self->destEnd <= (dest + size)) {
            size = self->destEnd - dest;
        }

        CacheDmac((void*) dest, (void*) line, size);
    }
    FlushDmac();
    UnlockDmac();
}

既にある自分の Cygwin 環境で gnupack の emacs だけ使ってみたい

うちの環境は 64bit Windows 10 で Cygwin 64bit 版を利用している。

emacsCygwin に入っていたのをターミナルで使っていたが、最近そぞろに GUI 版を使いたくなってきたので gnupack の emacs を入れることにした。

 

ここにその顛末を述べたいと思う。

 

gnupack をインストールする

gnupack Users Guide

gnupackの開発メモ

上記のサイトを参考にインストールする。

emacs だけ欲しいので

パッケージ emacs for gnupack - gnupack - OSDN

にある emacs 24.2 を入れればいいのかもしれないが、 gnupack に入っている emacs のほうが 24.5 とバージョンが新しいようなので欲を掻いて

gnupack_devel-13.06-2015.11.08.exe

を入れることにした。

 

インストール方法は Users Guide に記載あり。ほぼダウンロードして解凍するだけ。

C:\gnupack

にインストールした。

 

emacs の起動

もともと入っている 64bit 版 Cygwinbash を起動し、その中から gnupack Users Guide に書かれた startup_emacs.exe を使って起動を試みる。

 $ /cygdrive/c/gnupack/gnupack_devel-13.06-2015.11.08/startup_emacs.exe

 

起動するにはするが、これだと gnupack 専用の設定で起動してしまう。

 

HOMEの位置も変わってしまうし、いつも使っている .emacs も読んでくれない。

なんか変な感じ。

 

そこで、直接 emacs を起動してみる。

 $ /cygdrive/c/gnupack/gnupack_devel-13.06-2015.11.08/app/cygwin/emacs/bin/emacs.exe 

すると、ウィンドウがポップアップして落ちる。

どうやら 64bit 版 Cygwin からは直接起動できないらしい…。

 

おとなしく gnupack が作り上げた世界で生きていくことも選択肢の一つだが、ここではとりあえず、ふつうの Cygwin 環境で gnupack の提供する emacs だけ使えるようにしてみる。

 

32bit 版 Cygwin を入れる

64bit版 Cygwin からは直接起動できないようなので 32bit Cygwin を入れることにした。(ここで、「Cygwin を入れ直すなら gnupack の構築した世界で生きていけばいいのでは……」という葛藤としばし戦うことになる)

 

Cygwin は ==> こちら

setup-x86.exe (32-bit installation) を使う。 

この記事の執筆時点での最新は 2.5.1。

Cygwinのインストールについては64bit版の別の記事もご参考にどうぞ) 

 

32bit 版 Cygwin から emacs を直接起動してみる

インストールも無事終わり bash を起動して、そこから gnupack の emacs を起動してみる。

すると、下の warning が出て起動しない。 

$ /cygdrive/c/gnupack/gnupack_devel-13.06-2015.11.08/app/cygwin/emacs/bin/emacs
Warning: arch-dependent data dir `/app/cygwin/emacs/libexec/emacs/24.5/i686-pc-cygwin/': No such file or directory
Warning: arch-independent data dir `/app/cygwin/emacs/share/emacs/24.5/etc/': No such file or directory
Warning: Lisp directory `/app/cygwin/emacs/share/emacs/24.5/lisp': No such file or directory
Error: charsets directory not found:
/app/cygwin/emacs/share/emacs/24.5/etc/charsets
Emacs will not function correctly without the character map files.
Please check your installation!

 

/app をマウントする

どうやら gnupack の提供する /app が見えないために emacs が起動しないようなので gnupack についてきた /etc/fstab を参考に /app をマウントする。

 

gnupack の /etc/fstab

# For a description of the file format, see the Users Guide
# http://cygwin.com/cygwin-ug-net/using.html#mount-table
# This is default anyway:
# none /cygdrive cygdrive binary,posix=0,user 0 0
none / cygdrive binary,nouser,noacl,posix=0 0 0
C:/gnupack/gnupack_devel-13.06-2015.11.08/home /home ntfs binary,nouser,noacl,posix=0 0 0
C:/Users/ユーザー名/AppData/Local/Temp/gnupack /tmp ntfs binary,nouser,noacl,posix=0 0 0
C:/gnupack/gnupack_devel-13.06-2015.11.08/app/cygwin/local /usr/local ntfs binary,nouser,noacl,posix=0 0 0
C:/gnupack/gnupack_devel-13.06-2015.11.08 /root ntfs binary,nouser,noacl,posix=0 0 0
C:/gnupack/gnupack_devel-13.06-2015.11.08/app /app ntfs binary,nouser,noacl,posix=0 0 0
C:/Users/ユーザー名/Desktop /desktop ntfs binary,nouser,noacl,posix=0 0 0
C:/Users/ユーザー名/Desktop /top ntfs binary,nouser,noacl,posix=0 0 0

 

 /app は C:/gnupack/gnupack_devel-13.06-2015.11.08/app が本体らしいので、うちの Cygwin の /etc/fstab にも同じ設定を追加する。

# /etc/fstab
#
#    This file is read once by the first process in a Cygwin process tree.
#    To pick up changes, restart all Cygwin processes.  For a description
#    see https://cygwin.com/cygwin-ug-net/using.html#mount-table

# This is default anyway:
none /cygdrive cygdrive binary,posix=0,user 0 0
#none / cygdrive binary,nouser,noacl,posix=0 0 0
#C:/gnupack/gnupack_devel-13.06-2015.11.08/home /home ntfs binary,nouser,noacl,posix=0 0 0
#C:/Users/ユーザー名/AppData/Local/Temp/gnupack /tmp ntfs binary,nouser,noacl,posix=0 0 0
#C:/gnupack/gnupack_devel-13.06-2015.11.08/app/cygwin/local /usr/local ntfs binary,nouser,noacl,posix=0 0 0
#C:/gnupack/gnupack_devel-13.06-2015.11.08 /root ntfs binary,nouser,noacl,posix=0 0 0
C:/gnupack/gnupack_devel-13.06-2015.11.08/app /app ntfs binary,nouser,noacl,posix=0 0 0
#C:/Users/ユーザー名/Desktop /desktop ntfs binary,nouser,noacl,posix=0 0 0
#C:/Users/ユーザー名/Desktop /top ntfs binary,nouser,noacl,posix=0 0 0

 

とりあえず、全部コピペして /app 以外はコメントアウト。 /etc/fstab を保存して

$ mount  /app

を実行してマウント。

 

再度 emacsCygwin から実行してみる

 

$ /app/cygwin/emacs/bin/emacs  &

 

動いた!

 

その他の設定

gnupack の local に入っている諸々にアクセスできるように local もマウントしておいたほうがいいかもしれない。

 

でも /usr/local にマウントされるので、自分で /usr/local にインストールしたものがあるとそれは使えなくなる。

 

そういう向きは、とりあえず gnupack の local/bin に PATH だけ通しておいてもいいかもしれない。

 

.bashrc

  export PATH=/app/cygwin/local/bin:$PATH 

 

私の場合、32bit  Cygwin を入れたばかりで /usr/local には空の bin, etc, lib ディレクトリがあるだけなので mount してみた。

 

/etc/fstab で下の設定のコメントを外し

C:/gnupack/gnupack_devel-13.06-2015.11.08/app/cygwin/local  /usr/local  ntfs binary,nouser,noacl,posix=0 0 0

 /usr/local にマウントする

$ mount  /usr/local

こうすると gnupack に入っている日本語 man も表示出来てありがたい。

$ man 3 printf

 

PRINTF(3)                             Linux Programmer's Manual                            PRINTF(3)

名前
       printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 指定された書式に
       変換して出力を行う

書式
       #include <stdio.h>

       int printf(const char *format, ...);

...(後略)...

 

やってみたことリスト

今回は、とりあえず起動しただけ。まだ使い込んでいないのでちゃんと動くのか、ちょっと不安だけど、下のようなことは出来た。

  • Cygwinbash から gnupack の emacs を直接起動。OK
  • /app/cygwin/emacs/bin/emacs ~/.bashrc として自分の .bashrc が開く。(gnupack のホームのものではなく)
  • Cygwin の標準的なドライブ指定方式 /cygdrive/c で Cドライブにアクセス。OK。(gnupack では /cygdrive はマウントされない)
  • 日本語入力 OK。ATOK使えた。
  • テキストファイルに utf-8-unix で書いて保存。OK
  • M-x complile 実行。OK。 g++ -g -Wall -std=c++14 -o exe-name src-name.cpp を実行。コンパイルも通り、実行したら動いた。

 

ちょっと前には 64bit Windows では、 64bit Cygwin じゃないとダメなんじゃないかと思っていたけど、気のせいだったかな。それとも Cygwin のほうでなにか対処したのかな。 

 

最後に

今回は、既存の環境に gnupack の emacs だけを追加してみる方法を検討してみたが、その作業のあいだ gnupack が提供してくれる環境を使っていくなかで、これでもいいかな、いやむしろこっちのほうがいいかな、という気持ちに傾きつつある。

どうしよう。

 

とりあえず動いた memcpy4

 

// g++ -g -Wall -std=c++14 -o memcpy4 memcpy4.cpp
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <cstring>
#include <cassert>
#include <iostream>
using namespace std; #define ASSERTF(assertion, ...) do { if (!(assertion)) { assertf(__FILE__, __LINE__, __func__, __VA_ARGS__); }} while(0) void assertf(const char* file, int line, const char* func, const char* format, ...) { va_list ap; printf("%s:%d:%s: assertion failed: ", file, line, func); va_start(ap, format); vprintf(format, ap); va_end(ap); abort(); } // 4byte 単位でしかハードアクセスできないメモリコピー void memcpy4(void* dest, void* src, size_t size) { //memcpy(dest, src, size); size_t remain_size = size; // 残りのサイズ(バイト数) size_t copy_total = 0; // 読み取りバッファから書き込みバッファにコピーした総バイト数 // 読み取りデータの情報 size_t rd_boff = (size_t)src & 3; // 読み取り開始オフセット //size_t rd_eoff = rd_boff + size; // 読み取り終了オフセット(この値を含まない) size_t rd_beg = (size_t)src & ~3; // 読み取り開始アドレス //size_t rd_end = rd_beg + ((rd_eoff + 3) & ~3); // 読み取り終了アドレス(この値を含まない) // 書き込みデータの情報 size_t wr_boff = (size_t)dest & 3; // 書き込み開始オフセット size_t wr_eoff = wr_boff + size; // 書き込み終了オフセット(この値を含まない) size_t wr_beg = (size_t)dest & ~3; // 書き込み開始アドレス size_t wr_end = wr_beg + ((wr_eoff + 3) & ~3); // 書き込み終了アドレス(この値を含まない) // 読み取りバッファの情報 uint32_t rd_buf = 0; size_t rd_pos = rd_boff; size_t rd_remain = ((remain_size < 4) ? remain_size : 4) - rd_pos; // 書き込みバッファの情報 uint32_t wr_buf = 0; size_t wr_pos = wr_boff; size_t wr_remain = ((remain_size < 4) ? remain_size : 4) - wr_pos; // 読み取りバッファから書き込みバッファへのコピーサイズ size_t copy_size = (rd_remain < wr_remain) ? rd_remain : wr_remain; // 読み取りアドレス uint32_t* rd_addr = (uint32_t*) rd_beg; // 書き込みアドレス uint32_t* wr_addr = (uint32_t*) wr_beg; // 最初の一回目に wr_buf に読み込んでおくべきかどうか bool is_first_preload = ((wr_boff & 3) != (wr_beg & 3));
// 最後の一回で wr_buf に読み込んでおくべきかどうか
bool is_last_preload = ((wr_eoff & 3) != (wr_end & 3)); // 読み取りバッファに最初のデータを取得 rd_buf = *rd_addr; rd_addr += 1; // 最初の書き込みが 4byte アラインでない場合、範囲外のデータを壊さ // ないように書き込みバッファに読み込んでおく if (is_first_preload) { wr_buf = *wr_addr; } while ((size_t)wr_addr < wr_end) { rd_pos &= 3; rd_remain = (rd_remain != 0) ? rd_remain : ((remain_size < 4) ? remain_size : 4); wr_pos &= 3; wr_remain = (wr_remain != 0) ? wr_remain : ((remain_size < 4) ? remain_size : 4); copy_size = (rd_remain < wr_remain) ? rd_remain : wr_remain; for (size_t i = 0; i < copy_size; ++i) { ((char*)&wr_buf)[wr_pos + i] = ((char*)&rd_buf)[rd_pos + i]; } rd_pos += copy_size; rd_remain -= copy_size; wr_pos += copy_size; wr_remain -= copy_size; copy_total += copy_size; if (wr_remain == 0) { *wr_addr = wr_buf; wr_addr += 1; remain_size = size - copy_total; // 最後の書き込みが 4byte アラインでない場合、範囲外のデー // タを壊さないように書き込みバッファを読み込んでおく if (((size_t)wr_addr == wr_end - 4) && is_last_preload ) { wr_buf = *wr_addr; } } if (rd_remain == 0) { rd_buf = *rd_addr; rd_addr += 1; } } } int main(int argc, char* argv[]) { //assert(false); const size_t asize = 24; alignas(4) char obuf[asize] = {0}; alignas(4) char ibuf[asize] = {0}; size_t i; size_t opos; size_t ipos; size_t len; // input data for (i = 0; i < asize; ++i) { ibuf[i] = i; } for (opos = 0; opos <= 4; ++opos) { for (ipos = 0; ipos <= 4; ++ipos) { for (len = 8; len <= 16; ++len) { memset(obuf, 0, asize); memcpy4(obuf + opos, ibuf + ipos, len); for (i = 0; i < asize; ++i) { printf("%2d ", obuf[i]); } printf("\n"); fflush(stdout); for (i = 0; i < opos; ++i) { ASSERTF(obuf[i] == 0, "i=%d opos=%d ipos=%d len=%d obuf[i]=%d\n", (int)i, (int)opos, (int)ipos, (int)len, (int)obuf[i]); } for (; i < (opos + len); ++i) { ASSERTF(obuf[i] == ibuf[i - opos + ipos], "i=%d opos=%d ipos=%d len=%d obuf[i]=%d\n", (int)i, (int)opos, (int)ipos, (int)len, (int)obuf[i]); } for (; i < asize; ++i) { ASSERTF(obuf[i] == 0, "i=%d opos=%d ipos=%d len=%d obuf[i]=%d\n", (int)i, (int)opos, (int)ipos, (int)len, (int)obuf[i]); } } } } return 0; }

 

C++ Atomic operations についてのメモ

mutex が必要ないわけではないということ

atomic より粒度が大きいが現在でも有効な排他制御の手段。ということでいいかな。

 

粒度の細かい順に並べると

  1. atomic_thread_fence, atomic_flag
  2. atomic
  3. mutex, condition_variable
  4. lock_guard, unique_lock, once_flag, call_once
  5. future, promise
  6. packaged_task
  7. async

かな。

 

メモリロケーションについて

適切なメモリモデルを持たない場合、プロセッサが一度にロード・ストア可能なビット幅(1ワード)に複数の変数が割り当てられていると、複数のプロセッサから異なる変数を更新しに行ったとしても data race が起こる。

たとえば1ワード4byteのプロセッサで char arr[4]; と定義して arr[0] と arr[3] に別々のプロセッサから書き込みを伴う同時アクセスがあると data race 発生。(適切なメモリモデルが定義されていない場合)


static char arr[4] = {0};
thread t1{[&]{arr[0] = 1;}};
thread t2{[&]{arr[3] = 1;}};
t1.join(); t2.join();
cout << "arr= {" << arr[0] << "," << arr[3] << "}\n";


出力は arr = {0,1}, arr = {1,0}, arr = {1,1} のいずれかになる。(適切なメモリモデルが定義されていない場合)

(試しにやってみたが {1,1}にしかならないなあ。適切に定義されているということか)

 

メモリロケーションとは:

算術型の変数一つ、ポインタ一つ、非ゼロの幅を持つビットフィールドの並び(但し、たぶん1ワード幅未満)が、それぞれ占有するメモリ領域のこと。幅がゼロのビットフィールドはメモリロケーションの区切りとして使える。

異なるメモリロケーションであれば、複数スレッドが互いに干渉することなく読み書きできる。

 

 

データ競合(data race)

複数のスレッドが同じメモリロケーションに同時にアクセスして、一方が書き込みであれば、data race が発生する。read-modify-write 問題。

 

 

メモリオーダーについて 

Atomic operations ライブラリではデフォルトではアウトオブオーダー実行を抑制する。でいいのかな。つまりコードに書いてある順番で処理が実行される(ように見せる)

 
これは、デフォルトで、メモリーオーダー std::memory_order_seq_cst (sequentially consistent: 逐次一貫) に設定されているため。


高速化のため、ほかの memory_order も設定できる。という認識でいいかな。


http://en.cppreference.com/w/cpp/atomic/memory_order を少し翻訳(意訳)してみよう。

std::memory_order specifies how regular, non-atomic memory accesses are to be ordered around an atomic operation. Absent any constraints on a multi-core system, when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads. Some similar effects can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.

The default behavior of all atomic operations in the library provides for sequentially consistent ordering (see discussion below). That default can hurt performance, but the library's atomic operations can be given an additional std::memory_order argument to specify the exact constraints, beyond atomicity, that the compiler and processor must enforce for that operation.


std:: memory_order は、通常のメモリアクセス、つまり非アトミックなメモリアクセスが、アトミック操作を行う前後で、どのように並べ替えられるか(あるいは並べ替えられないか)を規定する。

メモリオーダーについて何の制約もないマルチコアシステムでは、複数のスレッドが複数の変数に同時にリード、ライトを行うとき、ある一つのスレッドが観測する変数の「変化の順番」は、変数を書いたスレッドが書き出した順番と必ずしも一致しない。

事実、読み出しを行う複数のスレッドの間では、変化の順番が見かけ上入れ替わる。

ユニプロセッサシステムでも、コンパイラによる順番の入れ替えが許されているメモリモデルを持つ場合、同じことが起こる。

ライブラリが提供するアトミック操作のデフォルトの振る舞いは、逐次一貫(sequentially consistent)である。

デフォルトの逐次一貫方式は、パフォーマンスを犠牲にしている。しかし、ライブラリのアトミック操作は std::memory_order 引数を取るので、逐次一貫以外の制約を与えることもできる。

コンパイラとプロセッサは操作をアトミックにするだけでなく、引数に与えたメモリオーダーの制約を適用してアトミック操作を行う責任を持つ。

 


memory_order_relaxed:

Relaxed operation: there are no synchronization or ordering constraints, only atomicity is required of this operation.

Relax操作:同期や順序の制約はない。アトミック性だけが、この操作に求められている。


memory_order_consume:

A load operation with this memory order performs a consume operation on the affected memory location: no reads in the current thread dependent on the value currently loaded can be reordered before this load. This ensures that writes to data-dependent variables in other threads that release the same atomic variable are visible in the current thread. On most platforms, this affects compiler optimizations only.

 

このメモリオーダーでのロードは、影響するメモリロケーションに対して「消費操作」を実行する。:

現在のスレッドでまだ読み込んでいない変更のうち、すでにロードされている値に影響するものが、ロードの前に読み込まれる。(RAMやCache上で値が変わっていたら、最新の値がそのスレッドに取り込まれる、ということらしい)

これは、同じアトミック変数を「解放(release)」した他のスレッド(複数可)の書き込みのうち、現在のスレッドに関係のある書き込みが、現在のスレッドで見えることを保証する。

多くのプラットフォームでは、これは、コンパイラの最適化にのみ影響する。

 

memory_order_acquire:

A load operation with this memory order performs the acquire operation on the affected memory location: no memory accesses in the current thread can be reordered before this load. This ensures that all writes in other threads that release the same atomic variable are visible in the current thread.

 


このメモリオーダーでのロードは、影響を受けるメモリロケーションの「獲得操作」を行います:

現在のスレッドでまだ読み込んでいない変更や書き込んでいない変更が、ロードの前に読み書きされる。(書き込みも? no memory accesses と言っているからそうだろうなあ)
これは、同じアトミック変数を「解放(release)」した他のスレッド(複数可)のすべての書き込みが現在のスレッドで見えることを保証する。


memory_order_release:

A store operation with this memory order performs the release operation: no memory accesses in the current thread can be reordered after this store. This ensures that all writes in the current thread are visible in other threads that acquire the same atomic variable and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic.

このメモリオーダーでのストアは、「解放操作」を行います。:

現在のスレッドでまだ読み込んでいない変更や書き込んでいない変更が、ストアのあとに読み書きされる。

これは、現在のスレッドによるすべての書き込みが、同じアトミック変数を「獲得」した他のスレッド(複数可)で見えることとを保証する。かつ、書き込みのうち、依存関係をアトミック変数に記録したものが、同じアトミック変数を「消費」した他のスレッド(複数可)で、見えることを保証する。


memory_order_acq_rel:

A read-modify-write operation with this memory order is both an acquire operation and a release operation. No memory accesses in the current thread can be reordered before this load, and no memory accesses in the current thread can be reordered after this store. It is ensured that all writes in another threads that release the same atomic variable are visible before the modification and the modification is visible in other threads that acquire the same atomic variable.

このメモリオーダーでの read-modify-write 操作は、「獲得操作」と「解放操作」の両方を行う。

現在のスレッドでまだ読み込んでいない変更や書き込んでいない変更が、ロードの前に読み書きされる。そしてストアのあとにまた読み書きが実施される。

これは、変更(modification)の前に、同じアトミック変数を「解放」した他のスレッドのすべての書き込みが見えることを保証し、現在のスレッドのすべての変更が、同じアトミック変数を「獲得」した他のスレットで見えることを保証する。

 

memory_order_seq_cst:

Same as memory_order_acq_rel, plus a single total order exists in which all threads observe all modifications (see below) in the same order.

memory_order_acq_rel と同じ。加えて、単一の全順序が存在する。
すなわち、すべてのスレッドにすべての変更が同じ順序で見える。

 

 

 

Windows 10 に teraterm を入れる

teraterm を入れた。

Tera Term (テラターム) プロジェクト日本語トップページ - OSDN

からダウンロードしてきてインストール。そのときのバージョンは 4.87

 

cygterm.cfg 消える問題

 

teraterm を Program Files (x86) フォルダにインストールした場合、変なことになる。

 

teraterm のメニューから何か設定(Cygwinの設定だけかな)をいじると、インストールフォルダにある cygterm.cfg が消えてしまう。

 

消えたものは C:\Users\<user-name>\AppData\Local\VirtualStore\Program Files (x86)\teraterm\cygterm.cfg として保存されるらしい。

 

しかし teraterm 側は相変わらずインストールフォルダしか見ないようで、ファイルがないと文句を言って起動しなくなる。

 

手でコピーして戻したら動いた。

 

※ インストール先が、システムで管理してるフォルダでなければたぶん消えない。teratermのリリースにZIP版もあるのはこのためかな。

 

TERATERM.INI の編集

  • VTPos=1000,0

ウィンドウの左上の角の位置を(x, y)(単位は画面解像度?)で指定するらしい。うちのマシンは 2560x1440 だが、1000で左上の角が画面の左右真ん中くらいになる。

f:id:nodamotoki:20150905151941p:plain

 

  • TerminalSize=103,54

一行に表示する文字数 103 と、ウィンドウに表示する行数 54 かな。

これは、teraterm のウィンドウの大きさを変えてメニューから設定の保存をすれば書き込まれるので、手作業で変える必要はなかった。

 

いじったのは、そんなところだったかな。